Pay an order
POST/api/v1/orders/{order_id}/payments
Overview
Pay an existing order’s accepted total through hosted Checkout or an approved saved card. Requires explicit API spending authorization and payments:write. Required Idempotency-Key protects retries for 24 hours; only one collection can be active per order. Declines and customer verification return payment state, not a new order.
Requires payments:write and administrator spending authorization.
Parameters
order_id path · required
Immutable order ID and customer reference: OM- followed by eight uppercase Crockford Base32 characters. Pass it unchanged; there is no separate order-number field.
string
Idempotency-Key header · required
Account, method and path scoped retry key, retained for 24 hours from first use. Same body replays the original successful status and body. A changed body returns 409 idempotency_key_reused; an in-flight request returns 409 idempotency_request_in_progress with Retry-After. Retry transient failures with the same key and body.
string
Request body
application/json
type string · required
Allowed values: checkout, saved_method
payment_method_id string · conditional
Min length: 1 · Max length: 243
Exactly one of these conditions applies:
checkout
Absent fields: payment_method_id.
type string · required
Always: "checkout"
saved_method
Required fields: payment_method_id.
type string · required
Always: "saved_method"
Responses
Payment state and optional interaction required; success of this HTTP call does not imply paid.
200 response
{
"order_id": "OM-XMF1NT2E",
"payment": {
"status": "requires_action",
"amount": 7000,
"currency": "usd",
"method": null,
"paid_at": null,
"receipt_url": null
},
"next_action": {
"type": "redirect",
"url": "https://payments.example.com/checkout/example",
"expires_at": "2026-09-18T19:00:00.000000Z"
}
}order_id string · required
Immutable order ID and customer reference: OM- followed by eight uppercase Crockford Base32 characters. Pass it unchanged; there is no separate order-number field.
Min length: 11 · Max length: 11
payment object · required
Order-bound payment state, independent of preparation/fulfillment. amount/currency come from accepted quote. A saved method or return redirect is not proof of payment. Receipt links may be absent; never expose client secrets here. Refund states describe full-order refunds in v1. Cancellation before production refunds the full accepted total, including shipping. Refund completion is asynchronous; refund_failed requires support.
payment fields
status string · required
Order payment state. Refund states describe full-order refunds.
Allowed values: unpaid, requires_action, processing, paid, failed, cancelled, refund_pending, refunded, refund_failed
amount integer · required
Minimum: 0
currency string · required
method object | null · required
method fields
At least one of these conditions applies:
object
id string · required
brand string · required
last4 string · required
null
null
paid_at string (date-time) | null · required
receipt_url string (uri) | null · required
Receipt link after successful payment, when available; otherwise null. Retrieve the order for current payment details.
error object · optional
Error code, message and optional field details. HTTP errors return this object directly; asynchronous processing errors appear on the resource. Branch on code, not message.
next_action object | null · required
next_action fields
At least one of these conditions applies:
redirect
type string · required
Always: "redirect"
url string (uri) · required
expires_at string (date-time) · required
null
null
Response headers
X-Request-IDRequest identifier for support. Send X-Request-ID with 8–64 ASCII letters, digits or hyphens to reuse that value; otherwise the server generates a UUID4 hex value. Include the returned X-Request-ID in support requests. Do not put secrets or account IDs in this value.
Idempotent-ReplayedPresent when the original successful response is replayed.
Errors
| HTTP | Code | What to do |
|---|---|---|
| 400 Bad Request | invalid_argument | A field, query parameter or header is invalid. Fix the field named in details, then send the request again. |
| 400 Bad Request | payment_method_not_found | No saved card with this ID is approved for the business. Choose a card from List payment methods. |
| 401 Unauthorized | unauthenticated | The API key is missing, invalid or revoked. Send a valid business API key in Authorization: Bearer. |
| 403 Forbidden | permission_denied | The key lacks the endpoint's scope, or payments lack spending consent. Check the scope listed on the endpoint. |
| 404 Not Found | order_not_found | No order with this ID exists in the account. Check the ID. |
| 409 Conflict | idempotency_key_reused | This Idempotency-Key was already used with a different body. Retry the original body, or use a new key for a new operation. |
| 409 Conflict | idempotency_request_in_progress | A request with this Idempotency-Key is still running. Wait Retry-After seconds, then retry the same key and body. |
| 409 Conflict | model_repair_estimate_pending | The repair fee is still being estimated. Wait until the model status is ready, then retry. |
| 409 Conflict | payment_in_progress | A payment with a different method is still in progress. Wait for its result before you try another method. |
| 409 Conflict | payment_method_unavailable | The saved card cannot be charged, for example because its billing address is invalid. Update it, then retry. |
| 409 Conflict | payment_reconciliation_required | The payment outcome is unknown and needs review. Contact support with the order ID; do not pay again. |
| 409 Conflict | payment_unavailable | The order cannot take a payment now. Retrieve it and check its status and expires_at. |
| 409 Conflict | quote_unavailable | A model, its price or its repair changed after quoting. Create and review a new quote. |
| 409 Conflict | repair_payment_pending | Another order has an unpaid repair fee for this file revision. Pay or cancel that order, then quote again. |
| 413 Content Too Large | request_too_large | The JSON body is over this endpoint's size limit. Send a smaller body. |
| 415 Unsupported Media Type | unsupported_media_type | The body is not JSON. Send Content-Type: application/json. |
| 429 Too Many Requests | resource_exhausted | A rate or account limit was reached. Wait at least Retry-After seconds, then retry. |
| 500 Internal Server Error | internal | The server failed unexpectedly. Retry with backoff; contact support with X-Request-ID if it persists. |
| 503 Service Unavailable | unavailable | A required service is briefly unavailable. Retry with backoff, reusing the same Idempotency-Key. |
API v1 preview