X-Numero-Signature header.
This is not limited to POST. Several GET endpoints that return tenant data — your balance, transfer status, transaction list, virtual accounts, cards, cardholders, customers and invoices — are signed too, so that a leaked read-only API key cannot read your account without the signing secret. Every page in the API reference states Signature required: Yes/No for its endpoint; that field is generated from the source code, so trust it over any example you find elsewhere.
How it works
- Take the exact JSON body you will send, byte for byte (camelCase property names)
- Compute an HMAC-SHA256 hash of it, using the UTF-8 bytes of your Public Key as the secret
- Base64-encode the resulting hash
- Send it in the
X-Numero-Signatureheader, along withX-Numero-Signature-Version: v2
Sign exactly what you send. The signature is verified against the raw body bytes on the wire. If you serialize the object twice — once to sign and once to send — and the two differ by even a space or key order, verification fails. Build the JSON string once, sign that string, and send that same string.
Code examples
Node.js
Python
C#
PHP
Full request example
Signing GET requests
SignedGET endpoints have no body, so the input is the canonicalized query string:
- URL-decode each value once.
- Sort parameters by key, case-sensitive (ordinal).
- If a key appears more than once, sort its values ordinally too.
- Join every pair as
key=value, separated by&. - If there is no query string at all, sign the empty string.
GET /api/v1/business/balance?currency=NGN signs the exact string currency=NGN — not the full URL, and not the path.
Check your implementation offline
You do not need to call Numero to know whether your signing code is right. These vectors are computed with the same HMAC the server uses, so if you reproduce all three you are correct. Using the keypk_test_numero_example_key:
Reproduce them from your shell:
Legacy headers
Older integrations send the API key asx-api-key and the signature as x-signature-key. Those still work and will keep being accepted, but new integrations should use the canonical X-Numero-Api-Key / X-Numero-Signature headers shown above.
Important notes
- The Public Key is the HMAC secret, used as its raw UTF-8 bytes — never Base64-decode it
- Property names in the JSON body must be camelCase
- Sign the exact bytes you send — no re-serialization between signing and sending
- Ensure your JSON serialization produces consistent output (no extra whitespace, consistent key ordering)