Skip to main content
The authentication and signing questions merchants ask most often. Full contracts: Acquiring API Specification.

Where do I get my API key?

Your API key is provided by Waffo during merchant onboarding. You can view it any time on Merchant Portal → Integration (Dev or Admin role required). Send it on every API request in the X-API-KEY header. Sandbox and production use different API keys — switch both the API domain and the key when you go live (see the go-live checklist).

What keys are exchanged between my system and Waffo?

At onboarding, you and Waffo exchange RSA public keys — each party keeps its own private key: Never send your private key to Waffo or commit it to a repository.

How do I sign an API request?

The signature algorithm is SHA256WithRSA. Use your merchant RSA private key to sign the whole body message of the request, and send the result in the X-SIGNATURE header alongside X-API-KEY. Waffo verifies it with the merchant public key you configured in the Portal and rejects the request with an invalid-signature error if verification fails. All requests are HTTP POST with Content-Type: application/json (UTF-8) over TLS 1.2 or above.

How do I verify Waffo’s API responses?

Waffo signs every response body with its own private key and returns the signature in the response’s X-SIGNATURE. Verify it with the Waffo public key (from Merchant Portal → Integration) using SHA256WithRSA before processing the response. If verification fails: investigate and contact Waffo, and stop sending new transactions until the issue is resolved — Waffo may already have processed your request even though you could not accept the response.

How do I verify webhook notifications?

Same mechanism as responses: each webhook request carries X-SIGNATURE, signed with the Waffo private key. Verify with the Waffo public key — SHA256WithRSA over the raw request body (do not JSON-parse and re-stringify), signature decoded from Base64 — and always verify before processing the event. The SDK’s handleWebhook() does this for you; full steps and Node.js/Go examples are in Webhook signature verification.

Do I sign my webhook response back to Waffo?

Yes. Your response to a Waffo callback also carries an X-SIGNATURE header, signed over the whole body message with your merchant private key. The body is {"message": "success / failed / unknown"} per your processing result.

What is the difference between A0001 and A0002?

I get A0001. What should I check?

  1. The X-API-KEY header is present and matches the key shown on Merchant Portal → Integration.
  2. You are not sending a sandbox key to the production domain (or vice versa) — each environment has its own key.

I get A0002. What should I check?

  1. You signed the whole body message — exactly the bytes you send, not a re-serialized copy.
  2. You signed with your merchant private key using SHA256WithRSA.
  3. The merchant public key configured on Merchant Portal → Integration matches that private key.
  4. After going live, you are using your production key pair — do not reuse the sandbox pre-generated keys.

How do I generate an RSA key pair?

Use openssl (https://www.openssl.org/source), as given in the specification appendix:
The go-live checklist also shows how to strip the PEM wrappers into the one-line Base64 values the Portal public-key field expects.

Who on my team can access the Integration page?

Viewing the API key and Waffo public key, and configuring your merchant public key, all require the Dev or Admin role in the Merchant Portal.

I have several merchant accounts. Can I use one API key across all of them?

No. Each API key is bound to a single merchant account (MID). A request authenticated with account A’s key can only operate on account A’s data — using it to query an order that belongs to account B fails, even though the key itself is valid. When you operate multiple MIDs, keep one key pair per account and always call with the key of the MID that created the order. A related lookup pitfall: subscription orders are not returned by the one-time payment Order Inquiry. Query subscriptions and their payment orders through the subscription-specific inquiry APIs instead.

Why does the SDK’s pay-method query return an empty payMethods array?

When you query your pay-method configuration through the SDK, the payMethods field in the result is always an empty array — this is expected. The real data is in payMethodDetails: one entry per contracted pay method, carrying productName, payMethodName, country, and currentStatus (whether the method is currently available). Iterate payMethodDetails to build the list of pay methods actually enabled under your contract for each country.