Square orders webhooks

Hi Team,

I have a few questions regarding Square webhooks:

  1. Does the order.created webhook get triggered for orders created through both Square POS and the Orders API? Similarly, does order.updated fire for updates made from both sources? If there are any exceptions, could you clarify them?

  2. From the documentation, it appears that the order.created and order.updated webhook payloads only include order metadata (such as order_id, version, and state) and not the complete order details (line items, modifiers, taxes, discounts, etc.). Is the recommended approach to call RetrieveOrder using the order_id to obtain the full order contents after receiving the webhook?

  3. When an order is partially refunded, individual items are refunded, or items are cancelled/returned, which webhook(s) should we rely on (order.updated, refund.created, refund.updated, or a combination)?

  4. If an item-level refund or return occurs, how can we determine which specific line items or modifiers were affected? Should we retrieve the latest order and inspect its returns section, or is there another recommended approach?

  5. Is there a reliable way to distinguish between:

    • a payment refund,
    • an item return/refund, and
    • an order/item cancellation,

    using webhook events and the subsequent API responses?

Thanks for the questions!

1. Trigger sources

Yes, order.created and order.updated fire for orders created/updated via Square POS, Square Online, the Orders API, Order Manager, and the Square Dashboard. The source field on the order object indicates the origin. See: Order Object - Square API Reference

2. Payload contents

Correct, the webhook payloads contain only metadata (order_id, version, state, location_id, timestamps), not the full order. Call RetrieveOrder with the order_id to get order detail. See: GET /v2/orders/{order_id} - Square API Reference

3. Refunds / cancellations webhooks

It depends on your use case. order.updated covers order-level state changes (cancellations, returns), while refund.created / refund.updated cover the monetary side. These don’t always fire together. For example, a goodwill refund won’t change the order, and a cancellation may not involve a refund. We’d recommend reviewing the webhook events reference and subscribing to the combination that matches your needs: Webhooks

4. Identifying affected line items

Call RetrieveOrder and inspect the returnsreturn_line_items array. Each entry includes source_line_item_uid mapping back to the original line item.

5. Distinguishing refund types

At a high level: check the order’s state (CANCELED = cancellation), the returns section (populated = item-level return), and refund.* events (monetary refund details). We’d recommend reviewing the Orders and Refunds API references together for the full picture:

Refunds and Exchanges
Refunds API

Hope that helps! Let us know if anything needs clarification.

Thanks for the response.
I have few more questions, if you could answer these please:

  1. If a merchant’s OAuth connection has fully expired (i.e., both the access token and refresh token are no longer valid), will Square continue to send webhook events for that merchant?
  2. If the merchant later reauthenticates and a new OAuth connection is established, will Square replay or deliver the webhook events that occurred while the connection was expired, or are those events permanently lost?

I was able to successfully created the return order and refund on sandbox environment for an order that I created via sandbox dashboard, however the return order is in open state and has not been completed till yet. Same issue with the refund, the refund remains stuck in pending state. Could you please guide me on how to transition them to the completed state, because it seems we cannot change the state of these directly via APIs and on sandbox dashboard these are not visible