Skip to content
ApiqDevelopers
API v1.64.0Open console
API referencepayments

Void payment

POST/v1/payments/{paymentId}/void
Idempotency-Key requiredAccepts X-Api-Key · oauthClientCredentials · bearer

Void an authorized, uncaptured payment — release the hold

Cancels the authorization of an intent that holds funds but has captured nothing: the intent becomes CANCELED and the provider releases the hold.Show moreCancels the authorization of an intent that holds funds but has captured nothing: the intent becomes CANCELED and the provider releases the hold. An intent that has captured any money is 409 CONFLICT — refund it instead (POST /v1/payments/{paymentId}/refund); an intent already CANCELED answers 200 with its state unchanged. Idempotency-Key is REQUIRED. The answer is provisional until the provider's webhook lands; the confirmation signal is payment.canceled. Harness provider only today. A post-booking operation on an intent that already exists: it stays up for a SUSPENDED tenant and, on the production deployment, for a tenant whose activation has not been approved, so its 403 is PaymentForbidden — never TENANT_SUSPENDED or TENANT_NOT_LIVE.

Path parameters

  • paymentIdstringRequired
    The paymentId returned by POST /v1/payments/intent

Headers

  • Idempotency-KeystringRequired
    Mandatory on mutations: **48h TTL**; replay with same body-hash returns the original response with Idempotency-Replayed true; same key + different body is 409 IDEMPOTENCY_CONFLICT; in-flight duplicate…Show moreMandatory on mutations: **48h TTL**; replay with same body-hash returns the original response with Idempotency-Replayed true; same key + different body is 409 IDEMPOTENCY_CONFLICT; in-flight duplicate is 409 IDEMPOTENCY_IN_PROGRESS.
  • X-Actor-KindstringOptional
    The channel that initiated a money verb: ai marks an AI-initiated call, which must then carry X-Approval-Token.Show moreThe channel that initiated a money verb: ai marks an AI-initiated call, which must then carry X-Approval-Token. The header is accepted for compatibility and can only mark a call ai, never un-mark one. New routes (POST /v1/approvals, /v1/agent-proposals) do not take it.
  • X-Approval-TokenstringOptional
    Redeemed by the payment verbs and by POST /v1/orders (orders.create), cancel (orders.cancel) and amend COMMIT (amend.commit).Show moreRedeemed by the payment verbs and by POST /v1/orders (orders.create), cancel (orders.cancel) and amend COMMIT (amend.commit). Human sessions and system keys are exempt. Single use, ~2 min TTL, bound to tenant + action + resource + amount; any drift fails closed and burns the token.

Request body

This operation takes no request body.

Responses

  • 200The payment intent after the voidPaymentIntentResponse
  • 400VALIDATION or UNKNOWN_DOMAINApiErrorResponse
  • 401
    UNAUTHENTICATED — missing or expired token.Show moreUNAUTHENTICATED — missing or expired token. Declared on every operation because `security` is declared globally at the document root: every route is authenticated, so every route can answer 401.
    ApiErrorResponse
  • 403PERMISSION_DENIED.ApiErrorResponse
  • 404NOT_FOUND — no such payment intent for this tenantApiErrorResponse
  • 405
    VALIDATION — the public edge serves GET, POST, PUT, PATCH and DELETE only; any other method is refused before the platform sees it (details.reason METHOD_NOT_ALLOWED, details.source edge).Show moreVALIDATION — the public edge serves GET, POST, PUT, PATCH and DELETE only; any other method is refused before the platform sees it (details.reason METHOD_NOT_ALLOWED, details.source edge). Not retryable as sent.
    ApiErrorResponse
  • 409
    CONFLICT | IDEMPOTENCY_CONFLICT | IDEMPOTENCY_IN_PROGRESS on capture, refund and void (a void of a payment that has captured money is INVALID_STATE with details.state CAPTURED: refund it instead).Show moreCONFLICT | IDEMPOTENCY_CONFLICT | IDEMPOTENCY_IN_PROGRESS on capture, refund and void (a void of a payment that has captured money is INVALID_STATE with details.state CAPTURED: refund it instead). CONFLICT carries details.reason: EXCEEDS_AUTHORIZED_REMAINDER (capture beyond what is authorized and not yet captured), EXCEEDS_REFUNDABLE, INVALID_STATE (details.state names the payment's state) or CONCURRENT_UPDATE. Never an over-capture or an over-refund. A payment whose cumulative refunds equal its captured amount moves to state REFUNDED; one whose refunds are below its captured amount and that has nothing left to capture is PARTIALLY_REFUNDED. Void adds BOUND_TO_ORDER (the payment is bound to an order — cancel the order) and PROVIDER_REFUSED.
    ApiErrorResponse
  • 414
    VALIDATION — the request URI (path and query string) is longer than 8 KiB; the public edge refuses it before the platform sees it (details.reason URI_TOO_LONG, details.source edge).Show moreVALIDATION — the request URI (path and query string) is longer than 8 KiB; the public edge refuses it before the platform sees it (details.reason URI_TOO_LONG, details.source edge). Not retryable as sent: send long input in the body of a POST.
    ApiErrorResponse
  • 429
    RATE_LIMITED — the API key or its tenant is over a rate limit; wait for Retry-After, then retry.Show moreRATE_LIMITED — the API key or its tenant is over a rate limit; wait for Retry-After, then retry. Every routed request is counted against two token buckets, the key's and the tenant's (all its keys together): 50 requests a second with a burst of 100 on the standard plan. Every travel verb except polling a search also spends from a supplier budget, per key and per tenant: 10 requests a second with a burst of 20, and a plan may add a daily quota of supplier calls. Answers carry the IETF RateLimit header fields for the tightest bucket consulted (RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, RateLimit-Policy); a refusal adds Retry-After and details.scope (KEY or TENANT), details.budget (PLATFORM or SUPPLIER), details.reason (RATE or DAILY_QUOTA), details.tier and details.retryAfterMs. A sandbox may run with the limiter off, in which case none of these headers is sent. A search that is still warming is a different answer with a different meaning (keep polling). with the key-velocity check on, also details.reason VELOCITY_LIMIT, a soft breach of the API key's own scope (components/responses/VelocityLimited), nextAction slow_down.
    ApiErrorResponse
  • 500INTERNAL — a bug, and traceId is the support handle.ApiErrorResponse
  • 501
    NOT_IMPLEMENTED — this deployment serves no payments: no payment provider is configured (provider=none), so every payment route answers 501.Show moreNOT_IMPLEMENTED — this deployment serves no payments: no payment provider is configured (provider=none), so every payment route answers 501. Not a capabilities-doc bug: payments are deployment configuration.
    ApiErrorResponse
  • 502Also the order read routes (getOrder, listOrderDocuments, listOrderEvents, searchOrders) when the order store times out: details.store names the store, retryable true.ApiErrorResponse
  • 503ApiErrorResponse

Errors you should handle

Branch on code and honour retryable — never on the HTTP status alone.

400VALIDATION
message.intent.checkOut must be after message.intent.checkIn
not retryable
400UNKNOWN_DOMAIN
Unknown domain 'HOTELS'. Did you mean HTL?
not retryable
401UNAUTHENTICATED
The bearer token is expired. Re-authenticate and retry.
not retryable
403PERMISSION_DENIED
Role lacks the required scope: payments:write
not retryable
404NOT_FOUND
No such payment intent.
not retryable
405VALIDATION
This method is not served.
not retryable
409CONFLICT
The capture exceeds the authorized amount not yet captured.
not retryable
409IDEMPOTENCY_CONFLICT
Idempotency-Key 7f0c33d1-9a1e-4d2c-9f77-1c0f2b3a4d55 was used with a different body; never executed
not retryable
409IDEMPOTENCY_IN_PROGRESS
A request with this Idempotency-Key is still in flight. Retry shortly.
retryable
414VALIDATION
The request URI is longer than 8 KiB.
not retryable
429RATE_LIMITED
Too many requests for this key on the supplier budget. Wait for the Retry-After interval before trying again.
retryable
500INTERNAL
An unexpected error occurred. Quote the traceId to support.
retryable
501NOT_IMPLEMENTED
This deployment serves no payments: no payment provider is configured.
not retryable
502UPSTREAM_UNAVAILABLE
Every supplier for HTL is circuit-open; no fan-out was attempted
retryable
503PROVIDER_DOWN
EXAMPLEHOTELS is unavailable; the order was not attempted and nothing was captured
retryable