Pre-Auth Requests

Pre-Authorization

Pre-authorization places a hold on a user's linked payment method without immediately capturing the funds. When your service completes and the final amount is known, you capture (settle) the hold. If the service doesn't proceed, you void it to release the funds.

Prerequisite: a paymentToken obtained from Account Linking.


Flow overview

sequenceDiagram
    autonumber
    participant ME as Merchant
    participant SB as ShopBack API

    ME->>SB: POST /tokenized-payment/v1/pre-auths
    Note over ME,SB: paymentToken, amount, currency, merchantRef
    Note over ME,SB: Header — X-ShopBack-Idempotent-Id: <uuid>
    SB-->>ME: 201 { id, status: AUTHORIZED, amount, currency }
    Note over ME,SB: Service runs — final amount determined
    ME->>SB: POST /tokenized-payment/v1/pre-auths/{id}/capture
    Note over ME,SB: { callbackUrl }
    SB-->>ME: 201 { orderUuid, status }
    SB-)ME: POST callbackUrl (async webhook)
    Note over ME,SB: { order_uuid, order_status: "SUCCESS" }

Pre-auth status lifecycle

AUTHORIZED ────────────────────────────────────┐
     │                                         │
     ▼                                         ▼
CAPTURE_INITIATED → CAPTURED            VOIDED
     │
     ▼
DECLINED  (authorization failed at PSP)
EXPIRED   (pre-auth not acted on within TTL)

Poll GET /tokenized-payment/v1/pre-auths/{id} after any write operation to confirm the transition.


Step-by-step

1. Create a pre-authorization

Request

POST /tokenized-payment/v1/pre-auths
Authorization: Bearer <merchant_jwt>
Content-Type: application/json
X-ShopBack-Idempotent-Id: 8a3f9c21-4b17-4e2d-9a31-dc702f81e934

{
  "paymentToken": "pt_sg_7829_a1b2c3d4e5f6...",
  "merchantUserId": "usr_7829",
  "amount": 25.00,
  "currency": "SGD",
  "merchantRef": "trip-4821",
  "merchantMetadata": {
    "pickupZone": "CBD",
    "vehicleClass": "standard"
  }
}
FieldRequiredDescription
paymentTokenYesToken from account linking, scoped to this user and your channel.
merchantUserIdYesMust match the merchantUserId used during account linking.
amountYesHold amount in major units (e.g. 25.00 for SGD 25.00). Must be > 0.
currencyYes3-letter ISO 4217 code. Must match your merchant channel's configured currency.
merchantRefYesYour stable, unique reference for this transaction (e.g. trip ID, booking ID). Used for idempotency — same merchantRef returns the same pre-auth within the idempotency window.
merchantMetadataNoArbitrary JSON object. Max 5 keys, 200 characters per value.
X-ShopBack-Idempotent-IdYes (header)UUID unique to this logical pre-auth attempt. See Idempotency.

Response

{
  "id": "9d2e1a87-3c4f-4b12-a891-cc702f81e123",
  "merchantRef": "trip-4821",
  "status": "AUTHORIZED",
  "amount": 25.00,
  "currency": "SGD",
  "orderUuid": null,
  "orderStatus": null,
  "merchantMetadata": {
    "pickupZone": "CBD",
    "vehicleClass": "standard"
  },
  "createdAt": "2026-06-24T09:00:00.000Z",
  "updatedAt": "2026-06-24T09:00:00.000Z"
}

A status of AUTHORIZED means funds are held. If you receive DECLINED, the hold was not placed — do not proceed with the service.


2. Poll for status (if needed)

If your create request times out or you need to confirm the hold before starting the service, poll:

GET /tokenized-payment/v1/pre-auths/{id}
Authorization: Bearer <merchant_jwt>

Poll until status is AUTHORIZED or a terminal state (DECLINED, EXPIRED).


3. Capture the pre-authorization

Once your service completes and the final amount is known, capture the hold to settle funds and create a ShopBack order.

📘

Capture amount

The current API captures the full pre-auth amount. If your final amount differs, contact ShopBack about partial capture support.

Request

POST /tokenized-payment/v1/pre-auths/9d2e1a87-.../capture
Authorization: Bearer <merchant_jwt>
Content-Type: application/json

{
  "callbackUrl": "https://your-app.com/shopback/webhook",
  "useCashback": true
}
FieldRequiredDescription
callbackUrlRecommendedHTTPS URL that ShopBack POSTs the order outcome to once the PSP confirms.
useCashbackNoApply the user's available ShopBack cashback to this payment. Defaults to true.

Response

{
  "uuid": "9d2e1a87-3c4f-4b12-a891-cc702f81e123",
  "orderUuid": "61cf9737-5cc3-421a-84c1-ba554c0674ba",
  "status": "APPROVED",
  "orderType": "ONLINE",
  "merchantRef": "trip-4821",
  "merchantOrderId": "SB-20260624-001",
  "consumerEmail": "u***@example.com",
  "failureReason": null,
  "createdAt": "2026-06-24T09:45:00.000Z"
}

4. Receive the webhook

If you provided a callbackUrl, ShopBack POSTs the final order outcome asynchronously once the PSP confirms:

{
  "order_uuid": "61cf9737-5cc3-421a-84c1-ba554c0674ba",
  "order_status": "SUCCESS",
  "order_context_token": "c9393a19-00b0-48cd-9a9e-fdcf0b3cdbb5",
  "cart_id": null,
  "webhook_url": "https://your-app.com/shopback/webhook"
}
⚠️

Treat the synchronous capture response as the source of truth

The webhook is best-effort. Always use the capture response status to determine payment outcome for your user. Use the webhook for reconciliation and downstream processing.


Voiding a pre-authorization

If the service doesn't proceed and you want to release the held funds before they expire:

Request

POST /tokenized-payment/v1/pre-auths/9d2e1a87-.../void
Authorization: Bearer <merchant_jwt>
Content-Type: application/json

{
  "reason": "User cancelled before service started"
}

Response

{
  "uuid": "9d2e1a87-3c4f-4b12-a891-cc702f81e123",
  "status": "VOIDED"
}
📘

Void only works on AUTHORIZED pre-auths

You cannot void a pre-auth that has already been captured, declined, or expired.


Error responses

HTTP statusError codeMeaning
400bad-requestMissing required field, amount ≤ 0, or currency mismatch
401payment-token.invalidToken not found, unlinked, or belongs to a different merchant
404pre-auth.not-foundPre-auth ID not found or belongs to a different merchant
409pre-auth.already-capturedCapture already initiated — do not retry
409pre-auth.already-voidedPre-auth was voided
409pre-auth.declinedAuthorization declined by PSP
409pre-auth.expiredPre-auth TTL elapsed without capture or void

Next step