Signing and Authentication
Credentials
Before calling OpenAPI, obtain an enabled set of OpenAPI credentials:
| Item | Description |
|---|---|
apiKey | Merchant Ed25519 public key as raw bytes in hex, also sent in the X-Api-Key request header. |
merchantPrivateKey | Merchant-held Ed25519 private key used to generate X-Signature. FuturePay does not store this private key. |
futurePayPublicKey | FuturePay Ed25519 public key as raw bytes in hex, used to verify FuturePay response signatures. |
Merchants can generate apiKey and merchantPrivateKey with OpenSSL:
openssl genpkey -algorithm ed25519 -out private_key.pem
openssl pkey -in private_key.pem -pubout -out public_key.pem
echo "Private Key (Hex )/merchantPrivateKey:"
openssl pkey -in private_key.pem -text | grep 'priv:' -A 3 | tail -n +2 | tr -d ':\n ' && echo
echo "Public Key (Hex)/apiKey:"
openssl pkey -pubin -in public_key.pem -text | grep 'pub:' -A 3 | tail -n +2 | tr -d ':\n ' && echoKeep merchantPrivateKey secure. After adding apiKey on the API Credentials page in the FuturePay merchant console, the system returns futurePayPublicKey / FPAPIKey.
Request Signature Headers
In production, all OpenAPI requests must include these headers, except operational paths explicitly exempted by FuturePay:
| Header | Type | Required | Description |
|---|---|---|---|
X-Api-Key | string | Yes | Merchant Ed25519 public key in hex. Supports 64-character raw public key hex; some 88-character formats are also supported for compatibility. |
X-Timestamp | string | Yes | Unix timestamp in milliseconds, such as 1784611200000. The default allowed window is 300 seconds before or after the server time. |
X-Nonce | string | Yes | Random string that must not repeat within the same tenant, environment, and time window. |
X-Signature | string | Yes | Ed25519 signature as 128-character hex, in lowercase or uppercase. |
Request Signing String
The signing string has this fixed format:
METHOD|PATH|TIMESTAMP|NONCE|QUERY_STRING|RAW_BODY| Component | Description |
|---|---|
METHOD | Uppercase HTTP method, such as GET or POST. |
PATH | Actual request path, excluding the domain and query string. Use the path received by the server. |
TIMESTAMP | Exactly matches X-Timestamp. |
NONCE | Exactly matches X-Nonce. |
QUERY_STRING | Raw query string without ?. An empty string when there is no query. |
RAW_BODY | Raw request body string. Use an empty string when signing multipart/form-data uploads. |
API pages show the full request path received by the server, such as /openapi/v1/cards/recharge. The signing PATH must exactly match the path in the actual request URL, without the domain or query string. Do not prepend an additional /openapi.
Signing Steps
- Generate a millisecond
timestamp. - Generate a random
nonce. - Prepare
rawBody. For JSON requests, use the exact JSON string sent over the wire; for GET requests and multipart uploads, use an empty string. - Join the components as
METHOD|PATH|TIMESTAMP|NONCE|QUERY_STRING|RAW_BODY. - Apply SHA-256 once to obtain a 32-byte digest.
- Sign the digest with the merchant Ed25519 private key.
- Encode the signature as hex and send it in
X-Signature.
Example signing string:
POST|/openapi/v1/cards/recharge|1784611200000|nonce-001||{"requestNo":"REQ001","cardId":"CARD001","amount":10,"currency":"USDT"}Response Signatures
FuturePay includes platform signature headers in responses after OpenAPI authentication has completed:
| Header | Type | Description |
|---|---|---|
X-FP-Api-Key | string | FuturePay Ed25519 public key in hex. |
X-FP-Timestamp | string | Millisecond timestamp when FuturePay generated the response signature. |
X-FP-Signature | string | FuturePay response signature in hex. |
X-FP-Body-Hash | string | SHA-256 hash of the response body in hex. |
To verify a response, use this signing string:
X-FP-Timestamp|RAW_RESPONSE_BODYApply SHA-256 to this string, then verify X-FP-Signature with the FuturePay public key corresponding to X-FP-Api-Key.
Merchant Webhook Callback
JSON webhooks sent to the merchant callback URL include the same four X-FP-* headers. The signing string is:
X-FP-Timestamp|RAW_CALLBACK_BODYVerify the signature using the raw request body as received. Do not parse and reserialize the JSON first. HTTP 2xx acknowledges successful receipt; timeouts, network errors, or non-2xx responses may cause redelivery.
Every callback payload includes a stable eventNo. FuturePay uses at-least-once delivery: automatic retries and manual replays preserve the same eventNo and request body. Use eventNo for idempotency.
See Merchant Webhooks for console configuration, event types, retry rules, and an integration checklist.
Authentication Error Responses
Authentication failures may return HTTP 401 or 403, while retaining the common response structure:
{
"code": 401,
"msg": "SIGNATURE_INVALID: 签名校验失败",
"data": null
}The Chinese text in the example response means “signature verification failed”; the actual response value is preserved above.
Common error codes:
| Error Code | HTTP Status | Description |
|---|---|---|
API_KEY_MISSING | 401 | X-Api-Key was not provided. |
API_KEY_INVALID | 401 | The API key does not exist, has an invalid format, or belongs to a different environment. |
REQUEST_HEADER_MISSING | 401 | X-Timestamp, X-Nonce, or X-Signature is missing. |
CREDENTIAL_DISABLED | 403 | The credential is not enabled, is disabled, or has expired. |
IP_NOT_ALLOWED | 403 | The source IP address is not on the allowlist. |
SIGN_TIMESTAMP_EXPIRED | 401 | The timestamp is outside the allowed window or has an invalid format. |
SIGNATURE_INVALID | 401 | Signature verification failed. |
NONCE_REPLAYED | 401 | The nonce has already been used within the time window. |
