Overview
Your API key identifies you. The request signature proves that an order request was created by someone holding your signing secret and that its fields were not changed on the way. C2C verifies the signature before it validates the request or runs any business logic. A request with a missing, malformed or incorrect signature is rejected with401, and no order is created.
The signature is a field named signature inside the JSON request body.
sksec_...) is issued together with your API key and is shown only once. Each API key has its own signing secret. Sign a request with the secret that belongs to the API key in that request’s C2C-API-Key header.Which endpoints require a signature
Signatures are required on requests that move money. Read-only requests are authenticated by your API key alone.Quick reference
Signature generation algorithm
Collect the fields you will send
signature.Drop what isn't signed
null or an empty string "", and fields whose value is an object or an array.Lowercase the keys
orderType → ordertype, merchantOrderRef → merchantorderref, callbackUrl → callbackurl.Sort by key
Build the query string
key=value pairs with &. Values are used as-is: no URL encoding and no JSON quoting.Append your signing secret
Hash
Send it
"signature": "<hex>" and send the body.Visual example
Value formatting rules
Numbers: 1500, 1500.5 and 1500.50 are different values
Numbers: 1500, 1500.5 and 1500.50 are different values
1500 signs as 1500 and 1500.50 signs as 1500.50. Most JSON libraries write 1500.5 for a floating-point 1500.50. That’s fine as long as the value you sign comes from the same object you serialize. Don’t use exponent notation such as 1.5e3.Optional fields
Optional fields
null produce the same signature. Every top-level field you send is signed, including fields C2C doesn’t use, so don’t add fields after signing.Key casing
Key casing
callbackUrl and CallbackURL both sign as callbackurl. A body that contains the same key twice in different cases (for example amount and Amount) is rejected with SIGNATURE_MALFORMED.metadata
metadata
metadata is a string. If it contains JSON, sign the string exactly as you send it, for example metadata={"cart":"A1"}.Worked examples
Use these inputs to check your implementation. All three use the example signing secretsksec_Q9mTz4Lk8XwR2bN6vH1cJ7pY3sF5gD0aE8uK2iOq (example only, not a real credential).
Code examples
Each example signs a payload and sends a deposit order. The helper signs the same object that is serialized into the body.How C2C validates a request
Order-creation requests pass through these checks in order. A request rejected at any step never reaches the next one.Signature error responses
traceId to support if you need help investigating a rejection.
Replay protection
A signature has no timestamp, so the same body always produces the same signature. C2C uses yourIdempotency-Key to tell retries from replays:
Idempotency-Key stay exactly the same. See Idempotency.
Common mistakes and troubleshooting
Debugging checklist
Reproduce the worked example
56eff91b5ab0351471a2a8d457320230.Print the query string
key=value joined with &, no signature, no null or empty values.Check the values
true/false, strings unescaped.Check the secret
sksec_, belongs to the same API key as your C2C-API-Key header, and is appended directly to the query string.Check the hash
Signing secret management
Keep it server-side
Keep it server-side
Store it like a password
Store it like a password
Rotate if exposed
Rotate if exposed
HTTPS only
HTTPS only
Migrating from header signatures
Replace the signing helper
Move the signature into the body
"signature": "<md5 hex>" inside the JSON body. Stop sending X-C2C-Timestamp and X-C2C-Signature; they are ignored.Stop signing GET requests
Keep retries on the same Idempotency-Key
Idempotency-Key.Test against the worked examples
X-C2C-Signature header.