Skip to main content
POST
Submit a payment request
request_id is your idempotency key for this call. Reusing it resumes the same payment; a new one starts a new payment; reusing it with different terms is refused with 409. See Idempotency.

Body

application/json

Structured payment request with sender authorization and optional W3C Verifiable Credentials

version
string
required

Semver-shaped declaration version (MAJOR.MINOR). The major component is locked to this schema's parent directory (v1 → major must be 1). Producers MUST emit the canonical value exported by the bindings' Version constant; the canonical bumps on each additive minor evolution.

Pattern: ^1\.[0-9]+$
Example:

"1.0"

request_id
string
required

Unique identifier for this payment request (used for idempotency)

Example:

"req_123456789"

source
object
required

Represents a cryptocurrency or token in a specific wallet. This tells the system what asset you're sending/receiving and which wallet to use.

destination
object[]
required

Array of destination assets for the settlement agent to choose from (at least one required, at most 16). The ceiling bounds the fan-out one request can buy: every consumer iterates this list.

Required array length: 1 - 16 elements
fulfillment_amount
string
required

The exact amount to be received at the destination (in the smallest unit, e.g., wei for ETH, cents for USD).

Example:

"1000000"

quote_deadline
string<date-time>
required

Required. The deadline for receiving price quotes from settlement providers. After this point no new quotes are accepted. The gateway injects no default and validates the value is in the future. The originator must supply it, and a request that omits it or supplies a past value is rejected with 400.

Example:

"2024-12-25T10:30:00Z"

fulfillment_deadline
string<date-time>
required

Required. The final deadline for completing the payment. If not completed by this time the payment fails and is eligible for a refund. The gateway injects no default and validates the value is in the future. The originator must supply it, and a request that omits it or supplies a past value is rejected with 400.

Example:

"2024-12-25T11:00:00Z"

sender_auth
object
required

Authorization from the asset owner to execute the payment. The exact format depends on the source blockchain's authorization mechanism.

max_source_amount
string

The maximum amount willing to be spent from the source (in the smallest unit).

Example:

"1000000"

settler_auth_required
object

Policy requirements for settler authentication. Keys are policy names, values indicate if the policy is required.

originator_auth
object

Optional identity verification using cryptographic credentials.

DEPRECATED. Credentials are moving to a holder-signed W3C VerifiablePresentation that travels alongside a request rather than inside it. That envelope is not part of this HTTP contract, so there is nothing here to move them to yet: treat this as a legacy carrier, and do not build a new integration on it.

quote_selector
string

Wallet address or public key of a trusted service that will automatically select the best exchange rate for your payment. Leave empty to use the default selector.

Example:

"0x742D35cC6634c0532925a3b844Bc9e7595F41360"

fulfillment_verifier
object

Third-party service that will independently verify your payment was delivered. Leave empty to use the default verifier.

escrow_contract_address
string

Escrow contract address, used to protect source funds until proof of fulfillment has been verified. Leave empty to use the default.

Example:

"0x742D35cC6634c0532925a3b844Bc9e7595F41360"

fulfillment_proxy
string

Fulfillment Proxy contract address, used to emit proof of fulfillment on the destination chain. Leave empty to use the default.

Example:

"0x892BB2e4F6b14a2B5b82Ba8d33E5925D42D4431F"

settler_requirements
object

Optional settler filtering requirements. If whitelist is present, only whitelisted settlers may win. If blacklist is present, blacklisted settlers are excluded. Both can be specified; blacklist takes precedence (a settler in both lists is rejected).

Response

Payment request submitted successfully

Response from submitting a payment request. If settlement completes inside the gateway's synchronous window, the response includes a fulfillment_confirmation with full settlement details. Otherwise you receive a payment_id plus the payment's current status, and can poll /v1/payments/{paymentId}/status for updates.

Read status before deciding what to do next: a pending or finalizing payment is in flight and must NOT be re-submitted under a new request_id (that would be a second payment), whereas a failed one is terminal — re-submitting it under the SAME request_id resolves to the same terminal payment, so a genuine re-attempt needs a new request_id.

A synchronously-completed payment carries proof of QUOTE as well as of delivery. When settlement lands inside the window you get status: completed, a full fulfillment_confirmation, and — since a quote necessarily was awarded to get there — quote_id and fulfillment_quote. The fast path therefore needs no follow-up call to verify: recompute quote_hash over the returned quote and compare it against the on-chain commitment from this response alone.

status is present on every response. completed is always accompanied by fulfillment_confirmation; failed is accompanied by error where a reason has been recorded.

payment_id
string
required

Unique ID for tracking this payment. Save this to check status later.

Example:

"0x761989729fefb4b0cb8b3e6f787301a3878c91e8fba35ed362a079292879f34f"

status
enum<string>
required

Where your payment is in its lifecycle. One payment reads the same however you ask about it.

  • pending: accepted and in progress. Nothing has reached the recipient yet.
  • finalizing: the transaction paying your recipient is on chain and is accruing the confirmations its chain requires. NOT FINAL, see below.
  • completed: delivered, with the required confirmations behind it.
  • failed: did not complete. Any funds held in escrow are returned, and error describes what went wrong.

completed and failed are final and will not change afterwards. pending and finalizing will.

Do not treat finalizing as delivered. It says the payment has been made on chain but is not yet irreversible, much as a card authorization is not yet a settlement. It normally becomes completed, and it can still become failed if the transaction never reaches the confirmation depth its chain requires. Acting on finalizing — releasing goods, crediting an account — means accepting that risk deliberately, at whatever threshold suits you rather than the one we wait for.

finalizing is about paying the recipient. While your own funds are still being committed on the source chain the payment is pending, because nothing has reached the recipient yet.

Available options:
pending,
finalizing,
completed,
failed
Example:

"pending"

idempotent_replay
boolean
required

Whether this response describes a payment that already existed, rather than one created by this request. true means the request_id had been used before and you are being handed the ORIGINAL payment — no second payment was created and nothing additional was charged.

Re-attempting a payment. Re-submit the same request and you get the same payment back. You may re-send the original bytes unchanged: the deadlines will have expired by then — quote_deadline bounds the auction and is short, while this endpoint may hold a submission for up to 30 seconds — and an expired deadline on a re-submission is not an error, because the request is resolved onto the payment that already exists rather than used to create one.

Re-signing with fresh deadlines is equally fine and returns the same payment. What you must NOT change is the request_id, and what you must not change under it is the payment's economics — source, destination, fulfillment_amount, max_source_amount — which are rejected with 409 IDEMPOTENCY_TERMS_MISMATCH. Deadlines and the signature are exempt precisely so that a re-attempt is possible.

A genuinely new payment needs a NEW request_id. In particular a failed payment is terminal: re-submitting its request_id keeps returning that dead payment, so recovering means starting a new one under a new key.

Present on every response, false for a newly created payment. A response without the field is from a gateway predating it, not a newly created payment.

This is the field to read when reconciling a suspected double charge: two submissions where the second reports true are one payment, whereas two both reporting false are two. It says nothing about how far the payment has got — read status for that.

Example:

false

transactions
object

The transactions a payment has produced, one entry per stage, added as each becomes known. A stage absent here has produced no transaction yet.

These are the two movements that decide whether your payment happened: your funds being committed, and your recipient being paid. Present on every outcome, so a payment that did not complete can still be traced on chain. fulfillment_confirmation is not a substitute: it is written only once a payment completes, and describes the finished delivery rather than progress towards it.

Where a stage is attempted more than once, the entry describes the attempt that counts — the one that succeeded, or the last one if none did.

quote_id
string

The winning quote's ID. Present when status is completed — a payment cannot settle without an award — and absent on a pending response, where no quote has been selected yet. Same value and meaning as on GET /v1/payments/{paymentId}/status.

Example:

"0x9a3b...e8d4"

fulfillment_quote
object

The settler-signed FulfillmentQuote for the winning quote, returned verbatim as an opaque signed document — the PREIMAGE of the quote_hash committed on-chain. Same value, semantics and canonicalization caveats as on GET /v1/payments/{paymentId}/status; see that field for how to verify it.

Present when status is completed. It may be absent even then, if the stored quote is unreadable: the award is reported through quote_id regardless, so a present quote_id with no fulfillment_quote means "verification preimage unavailable" and never "no quote was awarded". A consumer that requires the preimage should fall back to the status endpoint rather than treat the payment as unverified.

fulfillment_confirmation
object

Confirmation details after a payment has been successfully delivered. Contains proof of delivery and transaction details for both source and destination chains.

error
object

Why a payment failed. Present only when status is failed, and identical however you ask about the payment.

code is the stable, machine-readable identity of the failure — branch on it rather than on message, which is written for a person and may be reworded. docs_url points at the page describing that code.