Request signing

The create-payment endpoint requires an HMAC-SHA256 signature so that a captured API key alone cannot authorize requests: the caller must also possess the secret key and reproduce the exact canonical string including the body hash.

Algorithm summary

Step
Action

1

Take the raw HTTP body bytes (as sent on the wire).

2

Compute SHA-256 of those bytes; encode as lowercase hex (64 characters).

3

Build the signature base string (UTF-8, newline-separated lines).

4

Compute HMAC-SHA256 using your secret key as the HMAC key, over the signature base.

5

Encode the result as lowercase hex and send as X-Signature.

Signature base string

Four lines, separated by single newline characters (\n):

<METHOD>
<PATH>
<TIMESTAMP>
<BODY_SHA256_HEX>
Component
Rule

<METHOD>

HTTP method in uppercase (e.g. POST).

<PATH>

Path from the request URL only, no query string (e.g. /sdk/server/create-payment).

<TIMESTAMP>

Exact string sent in X-Timestamp (Unix seconds, decimal digits only).

<BODY_SHA256_HEX>

SHA-256 of raw body, lowercase hex.

The server uses the same construction and compares your X-Signature using a constant-time comparison.

Timestamp window

X-Timestamp must be a Unix time in seconds. The server rejects requests when abs(now - timestamp) > 300 (5 minutes). Synchronize your servers with NTP in production.

Raw body requirement

The HTTP application must preserve the raw request body for hashing. If your stack parses JSON before hashing, ensure the bytes used for the hash are identical to what you transmit. Re-serializing a parsed object can change whitespace or key order and will break the signature.

Node.js reference implementation

Common mistakes

Mistake
Result

Hashing JSON after pretty-printing differently than the wire format

INVALID_SIGNATURE

Including query string in <PATH>

INVALID_SIGNATURE

Using milliseconds instead of seconds in X-Timestamp

REQUEST_EXPIRED or validation errors

Wrong HTTP method casing

INVALID_SIGNATURE

Last updated

Was this helpful?