Capture an authorized payment
A capture describes the process of how merchants capture funds for an authorized payment. A capture is the second part of a two-part payment flow, and occurs after an authorized payment is finalized. Finalized payments have kind
set to authorization
. When a merchant wishes to capture the funds on an authorized transaction, Shopify sends a capture request to a payments app, and the app can resolve or reject it.
- The merchant clicks to capture the authorized payment.
- Shopify sends a backend request to the payments app, specifying the capture request.
- The app replies with a
201
and an empty response body. - The app finalizes the capture using the
captureSessionResolve
orcaptureSessionReject
mutation. - Shopify updates the payment status.
Initiate the flow
Anchor link to section titled "Initiate the flow"A capture can only be performed when the payment initiated by Shopify has a kind
property with a value of authorization
. With an authorization, you place a hold on funds and then reply to Shopify's capture request with the captureSessionResolve
or captureSessionReject
mutation to accept or reject the capture of funds respectively.
The capture flow begins with an HTTP POST request sent from Shopify to the payments app's capture session URL provided during app extension configuration:
Shopify must receive an HTTP 201
(Created) response for the capture session creation to be successful.
If the request fails, then it's retried several times. If the request still fails, then the user needs to manually retry the capture in the Shopify admin.
Request headers
Anchor link to section titled "Request headers"Header | Description |
---|---|
Shopify-Shop-Domain Required |
The permanent domain of the shop. Can be used to identify which shop is initiating the request. |
Shopify-Request-Id Required |
The unique request ID used to track specific requests for troubleshooting purposes. |
Shopify-Api-Version Required |
The API version selected in the payments app configuration. The version selected defines the response expected by the payments app. |
Request body
Anchor link to section titled "Request body"Attribute | Description | Type |
---|---|---|
id Required |
Unique identifier for the capture attempt. Used as the idempotency key. Assume that requests with a given ID are identical to any previously-received requests with the same ID. | String |
gid Required |
Identifies the capture when communicating with Shopify (in GraphQL mutations, for example). | String |
payment_id Required |
The ID of the authorized payment that is to be captured. | String |
amount Required |
The amount to be captured. The value is always sent using a decimal point as a separator, regardless of locale. | Numeric |
currency Required |
The three-letter ISO 4217 currency code. | String |
test Required |
Indicates whether the capture is in test or live mode. The test field is only sent if you select API version 2022-01 or higher in the payments app extension configuration in the Partner Dashboard. For more information, refer to Test a payments app.
| Boolean |
merchant_locale Required |
The IETF BCP 47 language tag representing the language used by the merchant. | String |
proposed_at Required |
A timestamp representing when the capture request was proposed. | String (ISO-8601) |
Resolve a capture session
Anchor link to section titled "Resolve a capture session"After you've successfully processed the capture request, you can resolve it by using the captureSessionResolve
mutation:
The id
argument corresponds to the gid
of the capture.
Reject a capture session
Anchor link to section titled "Reject a capture session"If you don't want to process a capture request, then you should reject it. You might want to reject a capture if authorization has expired or if you suspect that the request is fraudulent or high risk. You should only reject a capture in the case of final and irrecoverable errors. Otherwise, you should re-attempt to resolve the capture.
You can reject a capture using the captureSessionReject
mutation:
As part of the rejection, you need to include a reason why the capture was rejected as part of CaptureSessionRejectionReasonInput
.
The CaptureSessionRejectionReasonInput.code
is a CaptureSessionStatusReasonRejectionCode
, which is an enum of standardized error codes.
The CaptureSessionRejectionReasonInput.merchantMessage
argument is a localized error message presented to the merchant explaining why the capture was rejected.