Hex Pay Docs
API Reference

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

currencypayment_options.methodsInitial statuspaymentDetails
USD(omitted)createdabsent
TON(omitted)createdabsent
USD[{coin:"USDT",chain:"TON"}]pendingpopulated
TON[{coin:"USDT",chain:"TON"}]pendingpopulated
TON[{coin:"TON",chain:"TON"}]pendingpopulated

Optional fields

FieldTypeConstraintsDescription
ttlinteger (int64)900–43200, default 3600Payment window in seconds. Once elapsed, payment moves to expired.
order_idstringmax 128 charsYour internal order ID. Returned on all payment objects and in webhooks.
descriptionstringmax 512 charsHuman-readable payment purpose. May be shown to the customer.
metadataobjectmax 10 keys, string values up to 512 charsArbitrary key-value pairs for your own use. Returned in all responses and webhooks.
webhookURLstringHTTPS only, must be publicly reachableURL 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.

POST
/v1/payments
AuthorizationBearer <token>

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

X-Idempotency-Key?string

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.

Formatuuid
amountstring

The 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.

Match^(0|[1-9]\d*)(\.\d+)?$
currencystring

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.

payment_options?PaymentOptions

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.

ttl?integer

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.

Default3600
Formatint64
Range900 <= value <= 43200
order_id?string

Merchant-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.

Lengthlength <= 128
description?string

Human-readable description of the payment purpose. May be displayed to the customer on the payment page.

Lengthlength <= 512
metadata?object

Arbitrary 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.

Propertiesproperties <= 10

Empty Object

webhookURL?string

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.
Match^https://(?!localhost|127\.|0\.0\.0\.0|10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.)\S+
Formaturi
Lengthlength <= 512

Response 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"
  }
}