Create a payment
Creates a new payment for your store and returns the full payment object.
Requires a Bearer JWT token in the Authorization header.
Denomination
Set amount and currency to define what the customer owes.
amount— positive decimal string, e.g."100.00"or"1". No leading zeros on the integer part.currency— fiat code (USD,EUR,RUB) or coin ticker (TON,USDT,NOT,DOGS,BUILD,BLUM,DUST,DYOR,STON,XAUt0).
currency defines the unit of value, not the coin the customer pays with. The payment coin is controlled by payment_options.methods.
Checkout URL
Every payment response includes checkoutURL — the URL of the HexPay-hosted checkout page for this payment:
https://payment.hexpay.io/{paymentID}In Customer Choice mode, redirect the customer to checkoutURL so they can select a payment method. In Preselected mode, you can also send the customer directly there — they will land on the deposit screen.
Modes
Customer Choice — omit payment_options entirely. All store-enabled methods are shown to the customer at checkout. Payment starts in created status; paymentDetails is absent until the customer selects a method.
Preselected — pass payment_options.methods with exactly one entry containing both coin and chain. The server resolves the deposit address immediately. Payment is created directly in pending status with paymentDetails populated — the customer skips method selection and goes straight to the deposit screen.
Use the symbol values from GET /v1/payment-methods for coin and chain. Values are case-sensitive.
Supported combinations
currency | payment_options.methods | Initial status | paymentDetails |
|---|---|---|---|
USD | (omitted) | created | absent |
TON | (omitted) | created | absent |
USD | [{coin:"USDT",chain:"TON"}] | pending | populated |
TON | [{coin:"USDT",chain:"TON"}] | pending | populated |
TON | [{coin:"TON",chain:"TON"}] | pending | populated |
Optional fields
| Field | Type | Constraints | Description |
|---|---|---|---|
ttl | integer (int64) | 900–43200, default 3600 | Payment window in seconds. Once elapsed, payment moves to expired. |
order_id | string | max 128 chars | Your internal order ID. Returned on all payment objects and in webhooks. |
description | string | max 512 chars | Human-readable payment purpose. May be shown to the customer. |
metadata | object | max 10 keys, string values up to 512 chars | Arbitrary key-value pairs for your own use. Returned in all responses and webhooks. |
webhookURL | string | HTTPS only, must be publicly reachable | URL for the notification sent when the payment reaches completed. localhost and private IP ranges are rejected. |
Idempotency
Pass an X-Idempotency-Key header (UUID) to enable idempotent processing. When provided, retrying with the same key within 24 hours returns the cached response without creating a duplicate payment. Generate a fresh key for each logically distinct operation.
JWT token signed with the EdDSA algorithm. Obtain the token from the HexPay
merchant dashboard and pass it via the Authorization: Bearer <token> header.
In: header
Header Parameters
Optional UUID key for idempotent request processing. If the server receives two requests with the same key within a 24-hour window, the second returns the cached response from the first without creating a duplicate resource. Generate a fresh key for each logically distinct operation.
uuidThe payment value as a positive decimal string. No leading zeros are
permitted on the integer part ("007" is invalid; use "7").
For fiat currencies up to 2 decimal places are recommended.
For crypto tickers precision depends on the coin.
^(0|[1-9]\d*)(\.\d+)?$Ticker symbol for the denomination. Accepts fiat codes (e.g. USD, EUR,
RUB) or TON-ecosystem coin tickers (e.g. TON, USDT).
This field defines the unit of value — it does not determine the coin
the customer pays with. Payment coin is controlled by payment_options.methods.
For the full list of accepted values use GET /v1/payment-methods (coins)
or refer to the supported fiat codes in your store settings.
Optional constraints on which payment methods are available at checkout.
When omitted entirely, all payment methods enabled for your store are shown
and the payment is created in created status.
Time-to-live in seconds. Defines how long the payment remains active
from the moment of creation. Once the TTL elapses the payment moves to
expired status — this can happen from either created or pending.
Minimum: 900 (15 minutes). Maximum: 43200 (12 hours).
Defaults to 3600 (1 hour) if not specified.
3600int64900 <= value <= 43200Merchant-defined external order identifier. Use this to correlate a HexPay payment with your internal order or invoice system. Returned on all payment objects and included in webhook payloads.
length <= 128Human-readable description of the payment purpose. May be displayed to the customer on the payment page.
length <= 512Arbitrary key-value pairs for merchant use. All values must be strings. Returned on all payment objects and included in completed-payment webhook payloads. Maximum 10 keys; key names up to 64 characters, values up to 512 characters.
properties <= 10Empty Object
HTTPS URL to which HexPay will POST a webhook notification when this
payment reaches completed status.
Requirements:
- Must use HTTPS. Plain HTTP URLs are rejected.
- Must be publicly reachable from the internet. Loopback addresses
(
localhost,127.x.x.x) and private network ranges (10.x.x.x,192.168.x.x,172.16–31.x.x) are not allowed. - Make sure your server is configured to accept POST requests at this URL before creating payments.
^https://(?!localhost|127\.|0\.0\.0\.0|10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.)\S+urilength <= 512Response Body
curl -X POST "https://api.hexpay.io/v1/payments" \ -H "X-Idempotency-Key: a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \ -H "Content-Type: application/json" \ -d '{ "amount": "100.00", "currency": "USD", "order_id": "order-2026-00123", "webhookURL": "https://merchant.com/webhooks/hexpay" }'{
"id": "019327c6-2058-7901-b234-56789abcdeff",
"status": "created",
"order_id": "order-2026-00123",
"amount": "100.00",
"currency": "USD",
"checkoutURL": "https://payment.hexpay.io/019327c6-2058-7901-b234-56789abcdeff",
"timer": {
"createdAt": "2026-01-20T10:00:00Z",
"expiresAt": "2026-01-20T10:15:00Z"
}
}{
"error": {
"type": "invalid_request_error",
"message": "Amount must be a positive decimal number",
"code": "invalid_amount",
"param": "amount"
}
}{
"error": {
"type": "authentication_error",
"message": "Invalid or expired authentication token",
"code": "auth_invalid"
}
}{
"error": {
"type": "not_found_error",
"message": "The specified currency is not supported by HexPay",
"code": "currency_not_found",
"param": "currency"
}
}{
"error": {
"type": "rate_limit_error",
"message": "Too many requests. Please retry after a short delay.",
"code": "rate_limit_exceeded"
}
}{
"error": {
"type": "api_error",
"message": "An unexpected error occurred. Please retry the request or contact support.",
"code": "internal_error"
}
}