Skip to main content
Authorisation and capture is a two-step payment flow that allows merchants to reserve funds on a customer’s payment method before settling the transaction. It separates the moment of commitment from the moment of collection: authorisation confirms that funds are available and places a hold, while capture moves the money. This flow applies only to card payments. It is initiated by setting capture_method: manual when creating a payment session. If omitted, capture_method defaults to automatic, which settles funds immediately upon authorisation (standard sale behaviour).
capture_method is a best-effort, card-specific option. If the customer pays with a non-card payment method, the payment falls back to automatic capture regardless of the setting.

When to Use Authorisation and Capture

Reserve funds when a customer places an order, then capture when the item ships. If the item becomes unavailable, void the authorisation instead.
{
  "amount": 150000,
  "currency": "ZAR",
  "type": "one_time",
  "options": {
    "checkout_options": { "return_url": "https://merchant.example/return" },
    "payment_method_options": {
      "card": { "capture_method": "manual" }
    }
  }
}
Authorise the estimated amount (e.g. hotel stay), then capture the actual final amount. Void the remaining authorisation.For example, authorise R1 500.00 for a 3-night hotel stay. If the guest checks out after 2 nights (R1 000.00), capture R1 000.00 and void the remaining authorisation.
Authorise immediately, then review the transaction asynchronously. This gives your fraud team a window to review high-value or suspicious transactions before funds are settled. Capture after approval or void if flagged.
Authorise the full order amount, then capture per shipment as items become available. Void the remaining authorisation for any unshipped items.For example, a customer orders 3 items totalling R3 000.00. Ship item 1 (R1 200.00) and capture that amount. Ship item 2 (R800.00) and capture again. If item 3 is out of stock, void the remaining authorisation.
Authorise the base amount (e.g. a restaurant bill), then capture the final amount including the tip. Void the difference if the tip is less than the authorised buffer.For example, authorise R500.00 for a meal. The customer adds a R75.00 tip, so you capture R575.00 (if within the authorised amount) or capture R500.00 and process the tip separately.
Authorise a deposit amount when a customer begins a rental (e.g. car hire, equipment rental), then capture only the actual usage charges and void the remainder.For example, authorise R5 000.00 for a weekend car rental. The customer returns the car with no damage, so you capture R2 500.00 for the rental fee and void the remaining R2 500.00 deposit.
For simple, immediate payments where no review or delay is needed, use the default capture_method: automatic.

Payment Lifecycle

1

Create a Payment Session with capture_method: manual

Pass payment_method_options.card.capture_method: manual inside the session options:
POST /collect/payment_sessions

{
  "amount": 100000,
  "currency": "ZAR",
  "type": "one_time",
  "options": {
    "checkout_options": {
      "return_url": "https://merchant.example/order/123/status"
    },
    "payment_method_options": {
      "card": {
        "capture_method": "manual"
      }
    }
  },
  "external_reference": "order_123"
}
2

Customer completes authorisation

The customer is redirected to the checkout page (session_url) and completes the card payment. On success, the underlying payment object transitions to status: succeeded, meaning funds are reserved but not yet settled.The payment object at this stage:
{
  "id": "pay_rOaZNqKZMFxsRb2NBL1cj",
  "status": "succeeded",
  "intent": "payment",
  "amount": 100000,
  "currency": "ZAR",
  "capture_method": "manual",
  "authorised_amount": 100000,
  "paid_amount": 0,
  "voided_amount": 0,
  "authorisation_expires_at": "2026-03-25T09:00:44.224Z",
  "country": "ZA",
  "payment_method_details": {
    "type": "card",
    "card": {
      "type": "CREDIT",
      "scheme": "MASTERCARD",
      "bin": "527346",
      "last4": "3333"
    }
  },
  "external_reference": "order_123",
  "mode": "live",
  "created_at": "2026-03-18T09:00:44.224Z",
  "updated_at": "2026-03-18T09:01:12.531Z"
}
Webhook fired: payment.succeeded
3

Capture or void

You now have until authorisation_expires_at to act:
  • Capture the payment to settle funds (full or partial)
  • Void the authorisation to release the hold
  • Do nothing and let the authorisation expire automatically

Flow Diagram

Capture Scenarios

Full capture

Capture the entire authorised amount. Omit the amount field:
POST /collect/payments/pay_rOaZNqKZMFxsRb2NBL1cj/captures
Idempotency-Key: capture_order_123

// No request body needed
Response:
{
  "id": "pay_rOaZNqKZMFxsRb2NBL1cj",
  "status": "succeeded",
  "amount": 100000,
  "capture_method": "manual",
  "authorised_amount": 100000,
  "paid_amount": 100000,
  "voided_amount": 0,
  "authorisation_expires_at": "2026-03-25T09:00:44.224Z",
  ...
}
Webhook fired: payment.captured

Partial capture

Capture less than the full authorised amount by specifying amount:
POST /collect/payments/pay_rOaZNqKZMFxsRb2NBL1cj/captures
Idempotency-Key: capture_order_123_shipment_1

{
  "amount": 60000
}
Response:
{
  "authorised_amount": 100000,
  "paid_amount": 60000,
  "voided_amount": 0,
  ...
}
The remaining R400.00 of authorisation can be voided:
POST /collect/payments/pay_rOaZNqKZMFxsRb2NBL1cj/voids
Idempotency-Key: void_order_123_remainder

// No request body needed

Void

Full void

Release the entire remaining authorised amount:
POST /collect/payments/pay_rOaZNqKZMFxsRb2NBL1cj/voids
Idempotency-Key: void_order_123

// No request body needed
Response:
{
  "authorised_amount": 100000,
  "paid_amount": 0,
  "voided_amount": 100000,
  ...
}
Webhook fired: payment.voided

Void after partial capture

After a partial capture, void the remaining authorisation to close the payment:
1. Authorisation:         authorised_amount = 100000, paid_amount = 0,     voided_amount = 0
2. Partial capture 60000: authorised_amount = 100000, paid_amount = 60000, voided_amount = 0
3. Void remaining:        authorised_amount = 100000, paid_amount = 60000, voided_amount = 40000

Authorisation Expiry

Authorisations have a limited validity period, indicated by the authorisation_expires_at field on the payment object. After this time:
  • The authorisation can no longer be captured
  • Reserved funds are automatically released back to the customer by the card network
  • Attempting to capture returns a 409 Conflict error:
{
  "type": "https://docs.momentco.io/errors/conflict",
  "title": "Conflict",
  "status": 409,
  "detail": "The authorisation has expired and can no longer be captured.",
  "instance": "/collect/payments/pay_rOaZNqKZMFxsRb2NBL1cj/captures",
  "code": "conflict"
}
Authorisation validity periods vary by payment method and issuing bank, typically ranging from 5 to 30 days for card payments. Plan your capture workflow accordingly.

Error Handling

Conflict scenarios (409)

Captures and voids return 409 Conflict when the payment is not in a valid state for the requested operation:
OperationScenarioError detail
CapturePayment not authorised"The payment is not in an authorised state and cannot be captured."
CaptureAmount exceeds remaining"The capture amount exceeds the remaining authorised amount."
CaptureAuthorisation expired"The authorisation has expired and can no longer be captured."
VoidPayment not authorised"The payment is not in an authorised state and cannot be voided."
VoidAlready fully voided"The payment has already been fully voided."
VoidNo remaining authorisation"There is no remaining authorised amount to void."

Common Examples

E-commerce: authorise at checkout, capture at shipment

1. Customer places order for R1 500.00
2. Create session with capture_method: manual → authorise R1 500.00
3. Webhook: payment.succeeded (funds reserved)
4. Warehouse confirms stock and ships → POST /captures (full amount)
5. Webhook: payment.captured

Hotel: authorise estimated stay, capture actual amount

1. Guest checks in, estimated 3-night stay at R500/night
2. Authorise R1 500.00
3. Webhook: payment.succeeded (funds reserved)
4. Guest checks out after 2 nights → capture R1 000.00
5. Void remaining authorisation
6. Webhooks: payment.captured, then payment.voided

Pre-order: authorise, void if unavailable

1. Customer pre-orders limited item for R2 000.00
2. Authorise R2 000.00
3. Webhook: payment.succeeded (funds reserved)
4. Item becomes unavailable → void full amount
5. Webhook: payment.voided

Partial fulfillment: capture per shipment

1. Customer orders 3 items totalling R3 000.00
2. Authorise R3 000.00
3. Webhook: payment.succeeded (funds reserved)
4. Ship item 1 (R1 200.00) → capture R1 200.00
5. Ship item 2 (R800.00) → capture R800.00
6. Item 3 out of stock → void remaining authorisation
7. Webhooks: payment.captured (x2), payment.voided

Fraud review: authorise, review, then decide

1. Customer places R5 000.00 order
2. Authorise R5 000.00
3. Webhook: payment.succeeded (funds reserved)
4. Fraud team reviews (within authorisation window)
5a. Approved → capture full amount
5b. Flagged → void full amount

Tip adjustment: authorise base amount, capture with gratuity

1. Customer finishes meal for R500.00
2. Authorise R500.00
3. Webhook: payment.succeeded (funds reserved)
4. Customer adds R75.00 tip → capture R575.00 (within authorised amount)
5. Webhook: payment.captured

Rental deposit: authorise deposit, capture actual charges

1. Customer rents a car, R5 000.00 deposit required
2. Authorise R5 000.00
3. Webhook: payment.succeeded (funds reserved)
4. Customer returns car, rental fee is R2 500.00 → capture R2 500.00
5. Void remaining R2 500.00 deposit
6. Webhooks: payment.captured, then payment.voided

Complete End-to-End Example

A merchant selling electronics wants to authorise at checkout and capture at shipment. Step 1: Create payment session
POST /collect/payment_sessions

{
  "amount": 250000,
  "currency": "ZAR",
  "type": "one_time",
  "options": {
    "customer": {
      "name": "Lara",
      "email": "lara@example.com"
    },
    "checkout_options": {
      "return_url": "https://shop.example/order/ord_789/status"
    },
    "payment_method_options": {
      "card": {
        "capture_method": "manual"
      }
    }
  },
  "external_reference": "ord_789",
  "metadata": {
    "order_id": "ord_789",
    "items": "laptop,mouse"
  }
}
Step 2: Customer authorises (webhook received)
{
  "id": "evt_92847561234",
  "type": "payment.succeeded",
  "data": {
    "id": "pay_Xk9mPqR3sTuV7w",
    "status": "succeeded",
    "amount": 250000,
    "currency": "ZAR",
    "capture_method": "manual",
    "authorised_amount": 250000,
    "paid_amount": 0,
    "voided_amount": 0,
    "authorisation_expires_at": "2026-03-28T14:30:00.000Z",
    "country": "ZA",
    "payment_method_details": {
      "type": "card",
      "card": {
        "type": "CREDIT",
        "scheme": "VISA",
        "bin": "411111",
        "last4": "1234"
      }
    },
    "external_reference": "ord_789",
    "mode": "live",
    "metadata": {
      "order_id": "ord_789",
      "items": "laptop,mouse"
    },
    "created_at": "2026-03-18T14:30:00.000Z",
    "updated_at": "2026-03-18T14:30:45.123Z"
  }
}
Step 3: Laptop ships, capture R2 200.00
POST /collect/payments/pay_Xk9mPqR3sTuV7w/captures
Idempotency-Key: capture_ord_789_laptop

{
  "amount": 220000
}
Step 4: Mouse out of stock, void remaining authorisation
POST /collect/payments/pay_Xk9mPqR3sTuV7w/voids
Idempotency-Key: void_ord_789_mouse

// No request body needed
Final payment state:
{
  "authorised_amount": 250000,
  "paid_amount": 220000,
  "voided_amount": 30000
}

Webhooks

The following webhook events are emitted during the authorisation and capture lifecycle:
  • payment.succeeded Fired when the authorisation succeeds. The payment status is succeeded, authorised_amount is set, and paid_amount is 0. See payment.succeeded Event
  • payment.captured Fired when a capture succeeds (full or partial). The paid_amount field reflects the newly captured total. See payment.captured Event
  • payment.voided Fired when a void succeeds. The voided_amount field is incremented by the released amount while authorised_amount remains unchanged. See payment.voided Event
  • payment.attempt_failed Fired when an authorisation attempt fails. The last_payment_error field contains error details. See payment.attempt_failed Event
  • payment.failed Fired when all payment attempts are exhausted and the payment has failed terminally. The last_payment_error field contains details of the final failed attempt. See payment.failed Event
See the Payments API Overview for the full list of webhook events and error codes.