Skip to content

Signing and Authentication

Credentials

Before calling OpenAPI, obtain an enabled set of OpenAPI credentials:

ItemDescription
apiKeyMerchant Ed25519 public key as raw bytes in hex, also sent in the X-Api-Key request header.
merchantPrivateKeyMerchant-held Ed25519 private key used to generate X-Signature. FuturePay does not store this private key.
futurePayPublicKeyFuturePay Ed25519 public key as raw bytes in hex, used to verify FuturePay response signatures.

Merchants can generate apiKey and merchantPrivateKey with OpenSSL:

sh
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 ' && echo

Keep 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:

HeaderTypeRequiredDescription
X-Api-KeystringYesMerchant Ed25519 public key in hex. Supports 64-character raw public key hex; some 88-character formats are also supported for compatibility.
X-TimestampstringYesUnix timestamp in milliseconds, such as 1784611200000. The default allowed window is 300 seconds before or after the server time.
X-NoncestringYesRandom string that must not repeat within the same tenant, environment, and time window.
X-SignaturestringYesEd25519 signature as 128-character hex, in lowercase or uppercase.

Request Signing String

The signing string has this fixed format:

text
METHOD|PATH|TIMESTAMP|NONCE|QUERY_STRING|RAW_BODY
ComponentDescription
METHODUppercase HTTP method, such as GET or POST.
PATHActual request path, excluding the domain and query string. Use the path received by the server.
TIMESTAMPExactly matches X-Timestamp.
NONCEExactly matches X-Nonce.
QUERY_STRINGRaw query string without ?. An empty string when there is no query.
RAW_BODYRaw 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

  1. Generate a millisecond timestamp.
  2. Generate a random nonce.
  3. Prepare rawBody. For JSON requests, use the exact JSON string sent over the wire; for GET requests and multipart uploads, use an empty string.
  4. Join the components as METHOD|PATH|TIMESTAMP|NONCE|QUERY_STRING|RAW_BODY.
  5. Apply SHA-256 once to obtain a 32-byte digest.
  6. Sign the digest with the merchant Ed25519 private key.
  7. Encode the signature as hex and send it in X-Signature.

Example signing string:

text
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:

HeaderTypeDescription
X-FP-Api-KeystringFuturePay Ed25519 public key in hex.
X-FP-TimestampstringMillisecond timestamp when FuturePay generated the response signature.
X-FP-SignaturestringFuturePay response signature in hex.
X-FP-Body-HashstringSHA-256 hash of the response body in hex.

To verify a response, use this signing string:

text
X-FP-Timestamp|RAW_RESPONSE_BODY

Apply 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:

text
X-FP-Timestamp|RAW_CALLBACK_BODY

Verify 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:

json
{
  "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 CodeHTTP StatusDescription
API_KEY_MISSING401X-Api-Key was not provided.
API_KEY_INVALID401The API key does not exist, has an invalid format, or belongs to a different environment.
REQUEST_HEADER_MISSING401X-Timestamp, X-Nonce, or X-Signature is missing.
CREDENTIAL_DISABLED403The credential is not enabled, is disabled, or has expired.
IP_NOT_ALLOWED403The source IP address is not on the allowlist.
SIGN_TIMESTAMP_EXPIRED401The timestamp is outside the allowed window or has an invalid format.
SIGNATURE_INVALID401Signature verification failed.
NONCE_REPLAYED401The nonce has already been used within the time window.