Frequently Asked Questions
191 answers covering the full integration. Jump to a category, or press / to search everything.
General 12
What is GrowthBnk?#
GrowthBnk is a financial orchestration platform. It gives you a single, gateway-agnostic API to accept payments, and routes each transaction to the best-fit payment aggregator or gateway based on rules you configure — so you integrate once instead of building against every gateway.
What is payment orchestration?#
Payment orchestration is a layer that sits between your application and multiple payment gateways. It handles routing, retries, failover, reconciliation and reporting centrally, so you are not locked into a single provider and can optimise cost and success rates.
Why use payment orchestration instead of integrating a gateway directly?#
Direct integration ties you to one provider, one set of quirks and one point of failure. Orchestration lets you add or switch gateways without code changes, automatically retry or fail over when a gateway is down, route by cost/success-rate, and reconcile everything in one place.
Which payment gateways does GrowthBnk support?#
GrowthBnk integrates with major Indian aggregators and gateways (e.g. Razorpay, PayU, Cashfree, Paytm, Easebuzz) and can be extended to others. You never call a gateway directly — GrowthBnk selects one per your routing rules and returns a hosted payment_link.
Do I choose which gateway processes a payment?#
No. Gateway selection is server-side, driven by your routing configuration. This keeps your integration stable even as gateways are added, removed or reprioritised.
What is Test Mode (Sandbox)?#
Test Mode runs your integration against the sandbox environment (https://sandbox.growthbnk.com) using UAT gateways and test instruments. No real money moves, so you can build and verify the full lifecycle safely. See the Sandbox & Production guide.
How is the merchant onboarding flow structured?#
You sign up, complete business details and KYC, get sandbox credentials (API key + salt), integrate and test, then request production access. Once approved you receive production credentials and go live.
What credentials do I need to start?#
An API key (public identifier, sent as X-API-Key) and a secret salt (used to compute the request Hash, kept server-side). See Authentication.
Is GrowthBnk a payment gateway or does it hold funds?#
No. GrowthBnk is technology infrastructure that orchestrates acquirers and gateways you select. It does not receive, hold, control or disburse funds, and is not a merchant of record or financial institution.
What currencies are supported?#
Amounts default to INR. The currency field is accepted on payment creation; supported currencies depend on the routed gateway and your account configuration.
What is the difference between the API and the SDKs?#
The HTTP API (/v1/route/*) is the raw contract. The official Python/PHP/Node SDKs wrap it — computing the hash, retrying and verifying webhooks for you. Both are fully supported; see SDKs.
Where do I get support?#
Most integration questions are answered in this Help Center and the API reference. If you still need help, email developers@growthbnk.com with your merchant ID, order ID, transaction ID and timestamp — see Support.
Authentication 16
How do I generate a request signature (hash)?#
Compute the lowercase hex SHA-256 of a pipe-delimited string that starts with your API key and ends with your salt. The middle fields depend on the endpoint, e.g. for Initiate Payment: SHA256(key|merchant_transaction_id|transaction_amount|salt). Full formulas and code are on the Authentication page.
What headers are mandatory?#
X-API-Key (your key), Hash (the SHA-256 signature) and Content-Type: application/json for JSON bodies. Missing or wrong values return 401.
What is the API Key?#
A public identifier for your merchant account, sent in the X-API-Key header. It is not secret on its own — requests are authenticated by the Hash, which requires your salt.
What is the Secret Key / salt?#
The salt is a server-side secret used to compute the request hash. It is never transmitted. Anyone with your salt can sign requests as you, so treat it like a password.
Is there a separate Public Key?#
GrowthBnk uses an API key + salt (HMAC-style SHA-256) scheme rather than an asymmetric public/private keypair. The API key is the "public" identifier; the salt is the secret.
Which fields go into the hash for each endpoint?#
- Initiate Payment:
key|merchant_transaction_id|transaction_amount|salt - Transaction Status / Cancel:
key|merchant_transaction_id|salt - Refund Initiate:
key|transaction_id|refund_amount|salt - Refund Status:
key|refund_id|salt
What happens if hash validation fails?#
The API returns 401 Unauthorized with {"detail": "Invalid authentication hash."}. The request is not processed. Recompute the hash with the exact field values you send and your correct salt.
Why does my hash not match even though the values look right?#
Almost always a formatting mismatch: the hash is over raw string values, so "1499.00" and "1499.0" differ. Sign and send the identical string, use the correct field order, and confirm you are using the right salt for the environment.
How do I verify a webhook signature?#
Recompute SHA256(key|transaction_id|transaction_amount|salt) using the values from the webhook payload and compare, in constant time, to the hash header. Reject on mismatch. Code is on the Webhooks page.
Are authorization headers case-sensitive?#
HTTP header names are case-insensitive, but send them as documented (X-API-Key, Hash). Header values (the key and hex hash) are case-sensitive — the hash must be lowercase hex.
Do requests use a timestamp or nonce?#
The core /v1/route/* hash does not include a timestamp. Protect yourself with HTTPS (which prevents interception) and idempotent order IDs. Do not log or expose signed requests.
How does GrowthBnk protect against replay attacks?#
Always call over HTTPS/TLS so requests cannot be captured. Use a unique merchant_transaction_id per order so a replayed Initiate Payment cannot silently create a duplicate, and confirm outcomes server-side via status or webhook.
Can I rotate my API keys / salt?#
Yes. Rotate from your dashboard or via support. Rotate immediately if the salt may have been exposed. After rotation, update your server configuration; in-flight signed requests using the old salt will start failing with 401.
Is the API versioned?#
The current API is versioned in the path (/v1/route/*). Breaking changes would ship under a new version prefix; additive changes (new optional fields) are made in place.
What are the API rate limits?#
Traffic is rate-limited per API key. Exceeding your limit returns 429 Too Many Requests — back off and retry with jitter. If you need a higher quota, contact developers@growthbnk.com.
Can I call the API from the browser?#
No. Signing requires your salt, which must never reach the browser or a mobile app. Always sign and call the API from your server; expose only the resulting payment_link to the client.
Payment 16
How do I initiate a payment?#
POST to /v1/route/initiate_payment with merchant_transaction_id, transaction_amount, customer_details and your signed headers. You get back a hosted payment_link to redirect the customer to. See Initiate Payment.
How do I know a payment succeeded?#
Do not rely on the browser redirect. Confirm via a verified webhook or by calling Transaction Status. Only transaction_status = SUCCESS means paid.
What transaction statuses exist?#
Five: INITIATED, SUCCESS, FAILURE, DROP (customer abandoned) and CANCELLED. Gateway-native states like "pending" or "failed" are normalised into these.
Why is my payment stuck in INITIATED / pending?#
INITIATED means the payment was created but the customer has not completed it (or the final status has not been received yet). Poll Transaction Status with backoff, and rely on the webhook for the terminal state.
How do I cancel a payment?#
POST to /v1/route/transaction-cancel with the merchant_transaction_id. Cancellation only works while the transaction is still INITIATED. See Cancel Transaction.
Can I retry a failed payment?#
Yes — create a new payment attempt for the same order. Reuse the same merchant_transaction_id only if your account allows duplicates; otherwise generate a related but unique reference and reconcile on your side.
Can order IDs (merchant_transaction_id) be reused?#
By default merchant_transaction_id must be unique per merchant. Reuse is rejected unless your account explicitly permits duplicates. Use a fresh, unique ID per order to keep reconciliation clean.
What value must be unique per request?#
The merchant_transaction_id — your own order reference. It also feeds the auth hash for Initiate Payment. GrowthBnk additionally generates a globally unique transaction_id for each attempt.
What is the minimum payment amount?#
transaction_amount is in rupees and must be at least 1.00, with two-decimal precision. Amounts below ₹1.00 are rejected with a 400.
What customer details are required?#
customer_details is required and must include at least one of customer_email or customer_phone. Email must be valid; phone is digits only, 7–15 characters.
How long should I wait before checking status?#
Give the customer time to complete checkout. Prefer the webhook for near-real-time updates; if polling, start a few seconds after redirect and use exponential backoff rather than tight loops.
How should polling be implemented?#
Poll Transaction Status with exponential backoff (e.g. 2s, 4s, 8s, capped), stop once a terminal status (SUCCESS/FAILURE/DROP/CANCELLED) is returned, and always treat the webhook as the primary signal.
What is the payment_link and how long is it valid?#
payment_link is the hosted checkout URL you redirect the customer to. It is tied to the created transaction; once the transaction reaches a terminal state the link can no longer be paid.
Can I pass extra metadata with a payment?#
Yes — use the user-defined fields (udf1…udf10) for your own references. Note some fields may be reserved by the platform; keep your source of truth in your own database.
What happens if gateway initialisation fails?#
The API may return a success HTTP status with success: false and no payment_link. Always branch on the success flag, not just the HTTP code, and retry or route the customer to an error page.
Can I set success and failure return URLs?#
Yes — pass surl (success) and furl (failure) so the customer is redirected back after checkout. Treat these redirects as hints and still confirm the outcome server-side.
Transaction Status 8
Should I use polling or webhooks?#
Prefer webhooks — they are near-real-time and reduce load. Use Transaction Status polling as a backstop for missed webhooks and for on-demand confirmation (e.g. when a customer returns to your site).
How often should I poll?#
Use exponential backoff (e.g. 2s → 4s → 8s → 16s, capped at ~30s) rather than a fixed tight interval. Stop as soon as a terminal status is returned.
When should I stop polling?#
Stop once the status is SUCCESS, FAILURE, DROP or CANCELLED — these are terminal. Also stop after a sensible timeout and reconcile later if still INITIATED.
Why does the status endpoint return an array?#
A single merchant_transaction_id can map to multiple attempts (e.g. retries). Transaction Status returns them newest-first; use the most recent for the current outcome.
What id do I send to check status?#
Send your merchant_transaction_id in the body, with a hash of key|merchant_transaction_id|salt. See Transaction Status.
The status says SUCCESS but I did not get a webhook — what do I do?#
Treat Transaction Status as authoritative and fulfil the order. Then check your webhook endpoint (reachable, returns 200, signature verification correct) so future events are received.
Can status change after it becomes SUCCESS?#
Terminal states are final for the payment. Subsequent money movement (e.g. a refund) is tracked separately via the refund endpoints, not by changing the original transaction status.
What does DROP mean?#
DROP means the customer abandoned checkout without completing payment (e.g. closed the page). It is a terminal, unpaid state — you can create a new attempt for the order.
Refunds 14
How do I initiate a refund?#
POST to /v1/route/refund-initiate/ with the GrowthBnk transaction_id, a refund_amount and an optional refund_reason, signed with key|transaction_id|refund_amount|salt. See Refund Initiate.
Which id do I use to refund — merchant_transaction_id or transaction_id?#
Use the GrowthBnk transaction_id (the globally unique id returned at payment time), not your merchant_transaction_id. The refund hash is also computed over transaction_id.
Can I issue a partial refund?#
Yes. Pass a refund_amount smaller than the original. You can issue multiple partial refunds until the refundable balance is exhausted.
Can I issue multiple refunds on one payment?#
Yes, as long as the sum of non-failed refunds plus the new amount does not exceed the original payment amount. Track the remaining refundable balance on your side.
What are the refund limits?#
Total refunds cannot exceed the original transaction amount. Attempting to exceed it returns 400 with a message stating the remaining refundable balance.
Can I refund a payment that is not successful?#
No. Refunds are only allowed on transactions with status SUCCESS. Refunding a non-successful payment returns 400 "Refund is allowed only for successful transactions."
What refund statuses exist?#
Four: INITIATED, PROCESSING, SUCCESS, FAILURE. A refund starts as INITIATED and moves toward a terminal state.
How do I check a refund status?#
POST to /v1/route/refund-status/ with the refund_id (signed with key|refund_id|salt). Poll until refund_completed_at is set. See Refund Status.
Why is my refund pending / still PROCESSING?#
Refunds settle asynchronously at the gateway/bank. PROCESSING means it has been accepted and is in progress. Poll Refund Status; refund_completed_at becoming non-null signals a terminal state.
What does a failed refund mean and what do I do?#
FAILURE means the gateway could not complete the refund (e.g. instrument issue). Inspect the reason, and retry the refund or contact support with the refund_id and transaction_id.
How long does a refund take to process?#
Initiation is immediate, but funds reaching the customer depends on the gateway and issuing bank — typically a few business days. Use Refund Status to track the terminal state programmatically.
Is there a webhook for refunds?#
No dedicated refund webhook is emitted today. Poll Refund Status to detect completion.
Does the refund hash include the amount?#
Refund Initiate includes the amount: key|transaction_id|refund_amount|salt. Refund Status does not: key|refund_id|salt.
Webhooks 12
How do webhooks work?#
When a payment reaches a terminal state, GrowthBnk POSTs a signed JSON event to your configured URL with key and hash headers. Verify the hash, act on the event, and respond 200. See Webhooks.
How do I verify a webhook signature?#
Recompute SHA256(key|transaction_id|transaction_amount|salt) from the payload values and compare it, in constant time, to the hash header. Reject if it does not match.
How are webhook retries handled?#
If your endpoint does not return 200 (or times out), GrowthBnk retries delivery. Ensure your handler is fast and idempotent so retries are safe.
What is the webhook retry schedule?#
Failed deliveries are retried a bounded number of times with increasing intervals. Design for eventual delivery and reconcile with Transaction Status if an event is ever missed.
How do I handle duplicate webhooks?#
Make your handler idempotent: key on transaction_id (and event type), and ignore an event you have already processed. Retries and network conditions can deliver the same event more than once.
Can webhooks arrive out of order?#
Yes — do not assume ordering. Use the payload timestamps and your own state machine, and treat the latest verified terminal state as authoritative.
What is the webhook timeout?#
Respond quickly (well within a few seconds). Do heavy processing asynchronously after returning 200, otherwise the delivery may be treated as failed and retried.
What should my webhook endpoint return?#
Return HTTP 200 to acknowledge. Any other status, or a timeout, is treated as a failed delivery and retried.
What fields are in the webhook payload?#
Event type, transaction_id, merchant_transaction_id, transaction_status, transaction_amount, currency, timestamps, customer and merchant details, and fees. See the Webhooks payload reference.
Why am I not receiving webhooks?#
Check that the webhook URL is configured and public (not localhost), returns 200 quickly, is HTTPS, and that your firewall allows GrowthBnk. As a backstop, reconcile with Transaction Status.
Can I use webhooks and polling together?#
Yes, and you should. Use webhooks as the primary real-time signal and Transaction Status polling as a fallback for missed events.
What are webhook best practices?#
Verify the signature, respond 200 fast, process asynchronously, be idempotent, log the raw payload and headers, and reconcile periodically. See Webhooks → Best Practices.
Sandbox 12
What is the sandbox base URL?#
https://sandbox.growthbnk.com. Use your sandbox API key and salt; the request/response contract is identical to production.
What test cards should I use?#
Use the test instruments from the Sandbox guide, e.g. 4111 1111 1111 1111 for success and 4000 0000 0000 0002 for failure, plus UPI handles like success@upi / failure@upi. Real cards are rejected in sandbox.
How do I test a failed payment?#
Use a failure test instrument (e.g. the failure test card or failure@upi) on the hosted checkout. The transaction resolves to FAILURE.
How do I simulate a timeout?#
Sandbox provides test instruments/scenarios that leave a payment unresolved. Your integration should treat a long-unresolved payment as INITIATED and reconcile via Transaction Status.
How do I simulate a pending payment?#
Start a payment and do not complete checkout, or use a pending test scenario. The transaction stays INITIATED until it resolves or is cancelled.
How do I test refunds in sandbox?#
Complete a successful test payment, then call Refund Initiate with its transaction_id and poll Refund Status. No real money moves.
Why is KYC auto-approved in sandbox?#
Sandbox is for integration testing, so onboarding steps like KYC are auto-approved to let you get credentials quickly. Production enforces real KYC and approval.
Why does sandbox not move real money?#
Sandbox routes to gateway UAT environments, which simulate outcomes without touching real funds, cards or bank accounts. This lets you test safely.
Do webhooks fire in sandbox?#
Yes. Configure a reachable sandbox webhook URL and you will receive signed events for test transactions, verified the same way as production.
Can I reuse sandbox credentials in production?#
No. Sandbox and production have separate API keys and salts. Swap both the base URL and the credentials when going live.
Is sandbox data isolated from production?#
Yes. Sandbox transactions, settlements and configuration are entirely separate from production.
How do I know I am hitting sandbox vs production?#
By the base URL and credentials you configured. Keep them in environment variables so switching environments never requires code changes.
Production 10
What is the Go Live checklist?#
Verify API keys, whitelist IPs, configure webhook/return/redirect URLs, confirm hash and webhook verification, add retry/monitoring/logging, and swap to production credentials. See the Go Live Checklist.
How do I get production approval?#
Complete business details and KYC, finish sandbox integration testing, and request production access. Once approved you receive production credentials.
What is the production base URL?#
https://api.growthbnk.com. Use your production API key and salt.
How does production routing differ from sandbox?#
Production routes to live gateways per your configured rules and moves real money. The API contract is identical, so no code changes are needed beyond URL and credentials.
How should I monitor production?#
Track success/failure rates, webhook delivery, refund outcomes and error rates. Alert on spikes in 4xx/5xx, gateway failures and reconciliation mismatches.
What is a good rollback strategy?#
Keep the previous integration version deployable, gate new changes behind config, and be able to disable a problematic gateway via routing without a code deploy.
Do I need to whitelist IPs in production?#
If IP whitelisting is enabled on your account, only requests from your whitelisted server IPs are accepted; others get 403 "IP is not whitelisted." Keep the list current.
How do I switch from sandbox to production safely?#
Change the base URL and credentials via environment variables, re-run your Go Live checklist against a small real transaction, then ramp up traffic while monitoring.
Will my sandbox transaction IDs exist in production?#
No. Production issues its own IDs. Do not hardcode sandbox IDs; always store the IDs returned in the current environment.
Can I run sandbox and production in parallel?#
Yes — they are isolated. Many teams keep sandbox wired to staging and production to live, selected by environment configuration.
Routing 16
How does routing work?#
On each payment, GrowthBnk evaluates your active routing rules and selects a gateway server-side. You never specify the gateway in the request.
What routing strategies are available?#
Common strategies include priority/fixed, sequential, weighted, time-based and failover. Rules can also key off amount, bank, card or instrument type.
What is priority (fixed) routing?#
Gateways are tried in a fixed priority order; the highest-priority eligible gateway is used first.
What is weighted routing?#
Traffic is split across gateways by configured weights (e.g. 70/30), useful for load distribution or gradual migration.
What is sequential routing?#
Gateways are attempted in sequence; if one is ineligible or fails, the next in the list is tried.
What is failover routing?#
If the primary gateway is down or declines, the transaction automatically fails over to a backup gateway, improving success rates.
What is time-based routing?#
Different gateways are used depending on the time window (e.g. business hours vs off-hours), often to match gateway SLAs or costs.
What is amount-based routing?#
Rules select a gateway based on the transaction amount (e.g. high-value transactions to a specific acquirer).
What is bank-based routing?#
Routing decisions can consider the customer bank to pick the gateway with the best success rate for that bank.
How does card routing work?#
Card payments can be routed by network/issuer characteristics to the best-performing gateway for that card type.
How does UPI routing work?#
UPI transactions can be routed to the gateway with the best UPI success rates or lowest cost per your rules.
How does wallet routing work?#
Wallet payments are routed to gateways that support the chosen wallet, per your configuration.
Can routing change during runtime?#
Yes. Because selection is server-side and config-driven, you can change routing without redeploying your integration.
Can I disable a gateway temporarily?#
Yes. Disable it in your routing configuration and traffic shifts to the remaining eligible gateways — no code change required.
What happens if no routing rule matches?#
Initiate Payment returns 400 "No Routing Rule found for this amount." Ensure an active rule covers the request (e.g. the amount band).
Can I use multiple gateways at once?#
Yes — that is the point of orchestration. Configure several gateways and let routing/failover distribute and recover traffic across them.
Merchant Configuration 11
What is merchant configuration?#
Account-level settings that control your integration: enabled modules, connected gateways, connected banks, webhook URL, settlement settings, IP whitelist and business/KYC details.
What are connected banks?#
Bank accounts linked to your merchant profile, used for settlement and reconciliation of funds collected via gateways.
What are merchant payment gateways?#
The gateway integrations enabled on your account. Routing selects among these; disabling one removes it from routing.
What business details are required?#
Legal entity information used for onboarding, KYC and compliance. These must be accurate before production approval.
What is KYC and when is it required?#
Know Your Customer verification of your business. It is auto-approved in sandbox but mandatory for production access.
How do I configure my webhook URL?#
Set it in your dashboard. It must be a public HTTPS endpoint that verifies the signature and returns 200 quickly.
What is settlement configuration?#
Settings that determine how and when collected funds are settled to your connected bank account, and how settlement data is reported for reconciliation.
What are modules and module access?#
Features enabled on your account (e.g. payment orchestration, reconciliation). Calling an endpoint for a module you do not have returns 403 with a message naming the missing module.
How do I add IP whitelisting?#
Provide your server egress IPs in your account configuration. When enabled, only those IPs may call the API; others receive 403 "IP is not whitelisted."
Can I change configuration without code changes?#
Yes. Gateways, routing, webhook URL and most settings are configuration — changing them does not require redeploying your integration.
How do I get a "module access denied" error resolved?#
A 403 naming a module means that module is not enabled on your account. Contact support to enable it, then retry.
SDK 15
How do I install the Python SDK?#
pip install growthbnk. Then initialise the client with your API key, salt and base URL. See SDKs.
How do I install the PHP SDK?#
composer require growthbnk/sdk, then construct Growthbnk\Client with your credentials.
How do I install the Node.js SDK?#
npm install @growthbnk/sdk, then new GrowthBnk({ apiKey, apiSecret, baseUrl }).
How do I configure the SDK?#
Provide apiKey, apiSecret (your salt) and baseUrl (sandbox or production). Optional settings include timeout and max retries.
Should I use environment variables for credentials?#
Yes. Load the API key, salt and base URL from environment variables or a secrets manager — never hardcode them or commit them to source control.
How do I initialise the SDK?#
Create one client instance and reuse it. Example: gb = GrowthBnk(api_key=..., api_secret=..., base_url="https://api.growthbnk.com").
What is a minimal payment example with the SDK?#
Call payments.create(...) with your order id, amount and customer, then redirect to the returned payment link. Full examples are on the SDKs page.
Does the SDK compute the hash for me?#
Yes. The SDK signs each request and can verify webhooks, so you do not implement the hashing yourself.
How do I verify a webhook with the SDK?#
Call the SDK's webhook verify helper with the raw body and headers; it recomputes and compares the signature and throws on mismatch.
How do I configure timeouts in the SDK?#
Pass a timeout when constructing the client. Set it high enough for gateway calls but low enough to fail fast; pair with retries.
Does the SDK retry automatically?#
The SDKs retry idempotent/transient failures (e.g. network errors, 5xx) with backoff. Keep order IDs unique so retries are safe.
Does the SDK support connection pooling / reuse?#
Yes — reuse a single client instance so the underlying HTTP client pools and reuses connections instead of opening one per request.
How does the SDK handle exceptions?#
Errors are raised as typed exceptions (e.g. authentication vs authorization vs generic), exposing the backend message and HTTP status so you can branch on them.
Does the SDK support async?#
Use the SDK from your framework's worker/async context; for high concurrency, reuse the client and run requests concurrently rather than creating clients per call.
What are SDK logging best practices?#
Log request IDs, transaction IDs and status — never log the salt, full card data or raw signed requests. Redact secrets.
Performance 10
How do I handle high concurrency?#
Reuse a single SDK/HTTP client, run requests concurrently, keep handlers non-blocking, and rely on webhooks instead of tight polling loops.
Are the SDKs thread-safe?#
Client instances are designed to be shared across threads/workers. Avoid mutating shared state; create the client once at startup.
Is async supported?#
Yes, via concurrent execution in your runtime. The key is connection reuse and non-blocking webhook handling.
How should retries be tuned for performance?#
Use bounded retries with exponential backoff and jitter on transient errors only. Do not retry non-idempotent operations without a stable order id.
Should I cache anything?#
Cache configuration you fetch rarely, not payment state. Never cache the salt insecurely. Payment/refund status should be read fresh or driven by webhooks.
How do I tune the HTTP client?#
Set sensible connect/read timeouts, enable keep-alive/connection pooling, and size the pool to your concurrency.
How do I avoid connection churn?#
Reuse one client instance for the process lifetime so TLS connections are pooled and reused rather than re-established per request.
Does polling hurt performance?#
Tight polling wastes resources and can hit rate limits. Prefer webhooks; when polling, use exponential backoff and stop at terminal states.
How do I keep webhook processing fast?#
Verify, enqueue and return 200 immediately; process the event in a background worker. This avoids timeouts and retries.
How do I scale webhook handling?#
Terminate quickly and push events to a queue; scale workers independently. Ensure idempotency so parallel workers do not double-process.
Security 13
Should all traffic use HTTPS?#
Yes. Always call the API and receive webhooks over HTTPS/TLS. Never send credentials or signed requests over plaintext HTTP.
How should I store my secret salt?#
In environment variables or a secrets manager, encrypted at rest, with least-privilege access. Never commit it to source control or ship it to clients.
Why must I never expose the secret key?#
Anyone with your salt can forge valid signatures and act as you (initiate payments, refunds). Exposure is equivalent to leaking a password — rotate immediately if it happens.
What is IP whitelisting and should I use it?#
It restricts API access to your known server IPs. Enable it in production to reduce the blast radius if credentials leak; keep the list updated as infrastructure changes.
How do I prevent replay attacks?#
Use HTTPS, unique order IDs, and verify webhook signatures. Confirm outcomes server-side so a replayed client-side redirect cannot fake a payment.
What data should I never log?#
Never log the salt, full card numbers/CVV, or raw signed requests. Log identifiers (request/transaction IDs) and status instead, and redact sensitive fields.
How do I verify hashes securely?#
Use a constant-time comparison (e.g. hash_equals, hmac.compare_digest, crypto.timingSafeEqual) to avoid timing side channels.
What are the PCI considerations?#
Because checkout is hosted by GrowthBnk/the gateway, your servers generally never touch raw card data, reducing PCI scope. Do not collect or store card data yourself.
What OWASP practices apply?#
Validate and encode all inputs/outputs, protect secrets, enforce TLS, rate-limit your own endpoints, log securely and keep dependencies patched.
How do I secure my webhook endpoint?#
Require HTTPS, verify the signature before processing, accept only expected event shapes, and rate-limit/monitor the endpoint. Do not act on unverified payloads.
Can I restrict which operations a key can perform?#
Access is governed by the modules enabled on your account. Endpoints for modules you lack return 403. Contact support to adjust entitlements.
What should I do if my salt leaks?#
Rotate it immediately, review logs for unauthorised activity, and re-issue configuration. All previously valid signatures using the old salt stop working after rotation.
Should I validate the amount server-side?#
Yes. Always compute the amount on your server from your order, never trust a client-supplied amount, and sign exactly that value.
Errors 13
What does HTTP 400 mean?#
Bad Request — a missing/invalid parameter or a business-rule violation (e.g. amount below ₹1.00, no routing rule, non-refundable transaction). Read the message and fix the input.
What does HTTP 401 mean?#
Unauthorized — bad API key or a hash mismatch ("Invalid authentication hash."). Recompute the hash with the right fields, values and salt.
What does HTTP 403 mean?#
Forbidden — usually a missing module ("You do not have access to the '…' module.") or an IP not whitelisted ("IP is not whitelisted."). Fix account entitlements or the IP list.
What does HTTP 404 mean?#
Not Found — the referenced transaction or refund does not exist (or is not yours). Verify the id and that it belongs to the authenticating merchant.
What does HTTP 409 mean?#
Conflict — a duplicate or conflicting operation (e.g. reusing a unique order id, or cancelling something already processed). Use unique IDs and check current state first.
What does HTTP 422 mean?#
Unprocessable Entity — the request is well-formed but fails validation. Inspect the field errors in the response and correct them.
What does HTTP 429 mean?#
Too Many Requests — you exceeded your rate limit. Back off and retry with exponential backoff and jitter; request a higher quota if needed.
What does HTTP 500 mean?#
Internal Server Error — an unexpected server-side error. It is safe to retry with backoff; if it persists, contact support with the request/transaction id.
What does HTTP 502 mean?#
Bad Gateway — an upstream gateway returned an invalid response. Retry with backoff; if persistent, a gateway may be degraded (routing/failover can help).
What does HTTP 503 mean?#
Service Unavailable — a temporary outage or maintenance. Retry with backoff and monitor status.
What does HTTP 504 mean?#
Gateway Timeout — an upstream did not respond in time. The payment may still be processing; reconcile via Transaction Status before retrying so you do not double-charge.
What is the shape of an error response?#
Either {"success": false, "message": "…", "data": null} (service errors) or {"detail": "…"} (auth errors). Branch on the HTTP status, then read the message. See Error Codes.
Are there machine-readable error codes?#
Errors are conveyed via HTTP status plus a human-readable message string rather than separate numeric codes. Match on status and, where needed, the message text.
Best Practices 13
What is idempotency and why does it matter?#
Idempotency ensures a retried request does not create a duplicate effect. Use a unique, stable merchant_transaction_id per order so retries of Initiate Payment cannot double-charge.
How should I implement retries?#
Retry only transient errors (network, 5xx, 429) with bounded attempts and exponential backoff + jitter. Never blindly retry a timeout without reconciling first.
How should I set timeouts?#
Use explicit connect/read timeouts so requests fail fast, and pair them with retries. On a timeout, check Transaction Status before assuming failure.
What is exponential backoff?#
Increasing the wait between retries (e.g. 2s, 4s, 8s) with random jitter to avoid thundering-herd. Use it for polling and for retrying transient failures.
What is a webhook-first architecture?#
Treat verified webhooks as the primary source of payment state and use polling only as a fallback. It is faster, cheaper and more scalable than polling everything.
Why should I avoid tight polling?#
It wastes resources, can hit rate limits, and scales poorly. Prefer webhooks; when polling, back off and stop at terminal states.
Why use unique order IDs?#
They enable idempotency, clean reconciliation and safe retries, and prevent accidental duplicate charges.
Should I always verify signatures?#
Yes — verify the hash on every webhook before acting, using a constant-time comparison. Never trust an unverified payload.
What should I store for each transaction?#
Store your merchant_transaction_id, the GrowthBnk transaction_id, status, amount, timestamps and any request/response IDs for support and reconciliation.
Should I log request IDs?#
Yes. Log request and transaction IDs (not secrets) so you can trace issues and provide them to support quickly.
How do I monitor for failures?#
Alert on error-rate spikes, webhook delivery failures, gateway declines and reconciliation mismatches. Dashboards on success rate by gateway help catch degradations.
How do I handle duplicate callbacks?#
Deduplicate by transaction_id + event type and make processing idempotent, so repeated deliveries have no additional effect.
How do I reconcile transactions and settlements?#
Match your stored transactions against status and settlement data, and investigate mismatches (missing webhooks, timeouts, routing differences). Automate a daily reconciliation job.
Didn't find your answer? See Troubleshooting, the Common Mistakes guide, or contact support.