---
title: Monitoring and resiliency
description: >-
  Set up webhooks, handle disputes, manage order risks, and implement
  reconciliation for Shop Pay Wallet API.
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

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 webhooks documentation](https://shopify.dev/docs/apps/build/webhooks), 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/latest/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>") {
  token
  sourceIdentifier
  processingStatus {
    state
    message
    errorCode
  }
  order {
    id
    sourceIdentifier
    transactions(first: 10) {
      id
      kind
      errorCode
    }
    fulfillmentOrders(first: 10) {
      nodes {
        id
      }
    }
  }
  paymentRequest {
    total {
      amount
      currencyCode
    }
  }
}
}
```

***
