Skip to content

Create a payment from another chain

POST
/payments/cross-chain/create
curl --request POST \
--url https://hub.stablezact.com/api/v1/payments/cross-chain/create \
--header 'Content-Type: application/json' \
--header 'X-Public-Key: <X-Public-Key>' \
--data '{ "amount": 1, "originChainId": 1, "originCurrency": "example", "customerEmail": "hello@example.com", "callbackUrl": "https://example.com", "orderId": "example", "metadata": { "additionalProperty": "example" }, "expiresIn": 1800 }'

The customer pays on originChainId and you settle on your own chain, with the transfer bridged in between.

This endpoint reports failures with a code as well as a message, which the rest of the API mostly does not. Read the code rather than matching on the text.

Media typeapplication/json
object
amount
required
One of:
number
originChainId
required

The chain the customer pays from. Must be an EVM chain; anything else is refused with ORIGIN_NOT_SUPPORTED.

integer
originCurrency
required

The token the customer pays in on the origin chain.

string
customerEmail
string format: email
callbackUrl
string format: uri
orderId
string
<= 100 characters
metadata
object
key
additional properties
string | number | boolean | null
expiresIn

Seconds until the payment expires. Thirty minutes by default, which is longer than the fifteen a deposit-address payment gets, because a bridged transfer has more to do. Unlike the deposit window, this one is settable and is honoured to the second.

integer
default: 1800

Payment created.

Media typeapplication/json
object
success
boolean
payment
object
id
string format: uuid
status

Always pending on creation.

string
relayDepositAddress

Where the customer sends the origin-chain funds.

string
amountToSend

Amount in the origin token’s smallest unit.

string
amountToSendFormatted

The same amount, in whole tokens, for display.

string
originChainId
integer
originCurrency
string
destination

What you receive once the bridge completes.

object
network
string
currency
string
amount
string
expiresAt
string format: date-time
Examplegenerated
{
"success": true,
"payment": {
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"status": "example",
"relayDepositAddress": "example",
"amountToSend": "example",
"amountToSendFormatted": "example",
"originChainId": 1,
"originCurrency": "example",
"destination": {
"network": "example",
"currency": "example",
"amount": "example"
},
"expiresAt": "2026-04-15T12:00:00Z"
}
}

Rejected, with one of these codes:

  • ORIGIN_NOT_SUPPORTED: the origin chain is not EVM.
  • ORIGIN_REFUND_NOT_SUPPORTED: we could not refund on that origin chain if we had to, so the payment is refused rather than accepted with no way back.
  • NO_DESTINATION: your account has no settlement destination that works for this route.
Media typeapplication/json
object
success
boolean
error
required

Short machine-ish reason.

string
message

Longer explanation, when there is one.

string
code
string
Allowed values: ORIGIN_NOT_SUPPORTED ORIGIN_REFUND_NOT_SUPPORTED NO_DESTINATION
Example
{
"success": false,
"code": "ORIGIN_NOT_SUPPORTED"
}

Missing or invalid credentials.

Media typeapplication/json
object
success
boolean
error
required

Short machine-ish reason.

string
message

Longer explanation, when there is one.

string
Example
{
"error": "API credentials required. Use x-public-key header or x-api-key and x-api-secret headers."
}

The bridge has no route for this origin, destination and amount. Small amounts are the usual cause, since bridges have their own minimums.

Media typeapplication/json
object
success
boolean
error
required

Short machine-ish reason.

string
message

Longer explanation, when there is one.

string
code
string
Allowed value: NO_ROUTE
Example
{
"success": false,
"error": "Relay returned no route for this origin -> destination",
"code": "NO_ROUTE"
}