Integrate

API conventions

Base URL, response format, amounts, idempotency, retries and rate limits.

Base URL

text
/open/v1

Sandbox and production share the host. The environment is that of the API key that signed the request; a key only sees orders of its own environment (others return ORDER_NOT_FOUND), and out_order_no is unique per environment.

Response format

Responses use real HTTP status codes and one envelope:

json
{
  "trace_id": "6c1f0b9a3e2d4f5a",
  "status_code": 200,
  "message": "success",
  "data": { "id": "…", "status": "CREATED" }
}
json
{
  "trace_id": "6c1f0b9a3e2d4f5a",
  "status_code": 422,
  "message": "The amount exceeds the app's payment limit.",
  "error_code": "LIMIT_EXCEEDED"
}
  • Branch on error_code, never on message (English, may change).
  • Log trace_id and include it when contacting support.
  • INVALID_REQUEST messages name the field that failed — useful while developing.

Data formats

Type Format
Amount String, USDT, positive, at most 2 decimals on input ("5", "5.5", "5.50"); always 2 decimals on output. Never use floats.
Currency "USDT" only (CURRENCY_NOT_SUPPORTED)
Time RFC 3339 UTC, e.g. 2026-11-07T09:30:00Z
IDs HTP order id is a UUID. Your out_order_no / out_refund_no: 1–64 characters [A-Za-z0-9_-]
User OIDC sub string (max 128)

Idempotency

Create endpoints (POST /payments, POST /payments/{id}/refunds, POST /payouts) require an Idempotency-Key.

  • Same key + same body → the first successful response is replayed. Nothing is created twice.
  • Same key + different body → 409 IDEMPOTENCY_KEY_REUSED.
  • Same key while the first request is still running → 409 IDEMPOTENCY_IN_PROGRESS; retry shortly.
  • A request that failed does not consume the key: retrying it runs again.

Generate the key once per business operation (for example, store it with your order) and reuse it on every retry. Each retry still needs a fresh X-Nonce, X-Timestamp and signature.

out_order_no gives a second safety net: a different Idempotency-Key with an already used out_order_no returns ORDER_ALREADY_EXISTS.

Retries and timeouts

Situation What to do
Network error or timeout on a create Retry with the same Idempotency-Key, or look up GET /open/v1/orders?out_order_no=…
5xx, REPLAY_PROTECTION_UNAVAILABLE, IDEMPOTENCY_IN_PROGRESS Retry with exponential backoff
429 TOO_MANY_REQUESTS Wait for Retry-After seconds
Other 4xx Do not retry unchanged — fix the request

Rate limits

Signed requests are limited per app (default 600 per minute). Over the limit you get 429 with Retry-After: 60.

Body size

Request bodies are limited to 64 KB.