--- title: Monitoring and resiliency description: >- Set up webhooks, handle disputes, manage order risks, and implement reconciliation for Shop Pay Wallet API. api_name: commerce-components source_url: html: 'https://shopify.dev/docs/api/commerce-components/pay/monitoring' md: 'https://shopify.dev/docs/api/commerce-components/pay/monitoring.md' --- # Monitoring and resiliency **Note:** This API is **only available to select merchants and partners** using third-party checkout solutions. For more information, contact [our enterprise sales team](https://www.shopify.com/solutions/shop-pay/enterprise#contact-sales). It's highly recommended to instrument your integration with sufficient logging to gain insights into any errors thrown by your system. At a minimum, failure paths in your event handlers should all be considered, and notifications should alert your team of issues as needed. Shopify provides webhook subscriptions and APIs enabling multiple ways for you to monitor activity in your shop. The below guidelines are applicable to Shop Pay Wallet. *** ## Webhook Configuration At a minimum, you should be to setting up the following webhooks: | Webhook Topic | Description | | - | - | | `ORDERS_CREATE` | A webhook is sent every time an order is created. | | `ORDER_TRANSACTIONS_CREATE` | A webhook is sent every time an order transaction is created. | | `DISPUTES_CREATE` | A webhook is sent every time a dispute is created. This requires the `read_shopify_payments_disputes` scope on your custom app. | | `DISPUTES_UPDATE` | A webhook is sent every time a dispute is updated. This requires the `read_shopify_payments_disputes` scope on your custom app. | It's important to note that webhook delivery may be delayed, and must therefore never be depended on for real-time critical workflows such as completing a customer checkout. To learn more, see [the webhook best practices guide](https://shopify.dev/docs/apps/webhooks/best-practices), and our webhook topic resources for [GraphQL](https://shopify.dev/docs/api/admin-graphql/latest/enums/WebhookSubscriptionTopic) and [REST](https://shopify.dev/docs/api/admin-rest/latest/resources/webhook#event-topics) APIs. *** ## Creating a Webhook Subscription Example of creating new webhook subscription for the topic "ORDERS\_CREATE" using the `webhookSubscriptionCreate` mutation: ## Mutation ```graphql mutation webhookSubscriptionCreate($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) { webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) { webhookSubscription { id topic format uri } userErrors { field message } } } ``` ## Input ```json { "topic": "ORDERS_CREATE", "webhookSubscription": { "uri": "https://yoursite.com/webhooks/orders_create", "format": "JSON" } } ``` ## Response ```json { "webhookSubscriptionCreate": { "webhookSubscription": { "id": "gid://shopify/WebhookSubscription/1", "topic": "ORDERS_CREATE", "format": "JSON", "uri": "https://yoursite.com/webhooks/orders_create" }, "userErrors": [] } } ``` *** ## Handling Disputes A dispute, also known as a chargeback or inquiry, occurs when a customer questions the legitimacy of a charge with their financial institution. To effectively manage disputes, you must either subscribe to the appropriate webhook topics and [use the Shopify Admin API as necessary](https://shopify.dev/changelog/read-and-write-disputes-and-dispute-evidence-in-the-graphql-and-rest-admin-api), or manage the disputes through the Shopify admin. When a dispute is filed, you're able to provide additional information to support the legitimacy of the charge before the time limit. In any case, Shopify will ensure that evidence is submitted on your behalf, whether you take action or not. Orders may also be eligible for [Shopify Protect](https://help.shopify.com/en/manual/payments/shop-pay/shopify-protect), in which case Shopify will reimburse you for the disputed amount and chargeback fee if it is lost. For more information on dispute management, see the [Shopify Payments Disputes Documentation](https://help.shopify.com/en/manual/payments/shopify-payments/chargebacks). *** ## Order Risks Orders in Shopify will undergo a risk assessment after order creation. You can either [query the OrderRiskSummary](https://shopify.dev/docs/api/admin-graphql/latest/objects/OrderRiskSummary), or you can subscribe to the `ORDERS_RISK_ASSESSMENT_CHANGED` webhook. Orders can trigger automation events using [Shopify Flow](https://apps.shopify.com/flow) – see the [flow reference risk examples](https://help.shopify.com/en/manual/shopify-flow/reference/examples#risk) for details. *** ## Recovering from errors Although an order created event will be fired client-side when an order is completed, it's possible that a customer may close the window before the event is dispatched. In order to reconcile in such cases it is recommended to have a reconciliation job running on a schedule. *** ## Reconciliation job While webhook deliveries are recommended as the primary method for Shopify to trigger actions in your system, reconciliation jobs should always be implemented as well, as they serve multiple purposes: * In case the Shop Pay window is closed before the `paymentcomplete` event is dispatched * As a backup to webhooks, since webhooks may fail to be processed * To retrieve data which may not otherwise be available via webhook subscription ### Retrieving order data using the source identifier You can find [shopPayPaymentRequestReceipts](https://shopify.dev/docs/api/admin-graphql/unstable/queries/shopPayPaymentRequestReceipts) by their `source_identifier` (provided on `ShopPayRequestSessionCreate` mutation), which should correspond to the order in your system. For example, if the source identifier provided by your system for a given order was `your-source-id-1`, then you could issue a GraphQL request like below: ```graphql { shopPayPaymentRequestReceipts(first:10, query: "source_identifier:'your-source-id-1'") { nodes { token sourceIdentifier processingStatus { state message errorCode } order { id sourceIdentifier transactions(first: 10) { id kind errorCode } fulfillmentOrders(first: 10) { nodes { id } } } paymentRequest { total { amount currencyCode } } } } } ``` Note that while the above example request could result in multiple matching receipts, there will only be one corresponding order for a successfully completed receipt. The order may have multiple transactions (including failed payment attempts), fulfillmentOrders and lineItems. Because of this, your system must filter the results received. For example with transactions you would filter by `kind: "authorization"` and `status: "success"` to identify the transaction authorization ID needed when capturing payment. It's recommended to modify this example query to only retrieve the data required by your system, and introduce [pagination](https://shopify.dev/docs/api/usage/pagination-graphql) where necessary. ### Retrieving order data using the receipt token Alternatively, order data can be retrieved using the `shopPayPaymentRequestReceipt` query. The receipt token is returned from the [`ShopPayPaymentRequestSessionSubmit`](https://shopify.dev/docs/api/commerce-components/pay/graphql-pre-payment#example-shoppaypaymentrequestsessionsubmit) mutation. This query can be used to find the status of the payment request receipt. The status can be `processing`, `completed`, `action_required` (for example, if the customer needs to complete a 3DS authentication. This is automatically handled by Shop Pay popup), or `failed`. The `processingStatus` `message` and `errorCode` can be used to provide more information about the status for failed receipts. ```graphql query { shopPayPaymentRequestReceipt(token: "") { token sourceIdentifier processingStatus { state message errorCode } order { id sourceIdentifier transactions(first: 10) { id kind errorCode } fulfillmentOrders(first: 10) { nodes { id } } } paymentRequest { total { amount currencyCode } } } } ``` ***