Sign In

Top 50 Integration Mistakes

Each one lists the problem, the root cause, and the fix. Skim these before you go live.

1

Signing the wrong amount string

Problem

Requests fail with 401 Invalid authentication hash even though the amount looks correct.

Why it happens

The hash is over the raw string; "1499.0" and "1499.00" differ.

How to fix

Hash and send the identical two-decimal string, e.g. "1499.00".

2

Wrong field order in the hash

Problem

Signature never validates.

Why it happens

Fields were concatenated in the wrong order or a field was omitted.

How to fix

Follow the exact per-endpoint formula, e.g. key|merchant_transaction_id|transaction_amount|salt.

3

Using the wrong salt for the environment

Problem

Auth works in sandbox but fails in production (or vice versa).

Why it happens

Sandbox and production have different salts.

How to fix

Load the salt from environment config per environment; never share credentials across environments.

4

Exposing the secret salt to the client

Problem

Anyone can forge valid requests.

Why it happens

The salt was embedded in browser or mobile code.

How to fix

Sign only on the server; never ship the salt to a client.

5

Trusting the browser redirect as proof of payment

Problem

Orders marked paid that were never actually paid.

Why it happens

The redirect can be spoofed or interrupted.

How to fix

Confirm server-side via verified webhook or Transaction Status before fulfilling.

6

Not verifying the webhook signature

Problem

Fraudulent or malformed payloads are processed.

Why it happens

The handler acted on the payload without checking the hash header.

How to fix

Recompute the hash and constant-time compare before acting.

7

Non-idempotent webhook handling

Problem

Duplicate fulfilment or double emails.

Why it happens

The same event is delivered more than once and processed each time.

How to fix

Deduplicate by transaction_id + event type; make processing idempotent.

8

Slow webhook responses

Problem

Webhooks get retried repeatedly.

Why it happens

The handler does heavy work before returning 200 and times out.

How to fix

Verify, enqueue, return 200 immediately; process asynchronously.

9

Reusing order IDs

Problem

Initiate Payment returns Already exists.

Why it happens

merchant_transaction_id must be unique per merchant.

How to fix

Generate a unique order id per attempt; reconcile retries on your side.

10

Refunding by merchant_transaction_id

Problem

Refund returns 404 Transaction not found.

Why it happens

Refunds reference the GrowthBnk transaction_id, not your order id.

How to fix

Store the returned transaction_id and use it for refunds.

11

Refunding a non-successful transaction

Problem

400 Refund is allowed only for successful transactions.

Why it happens

Only SUCCESS payments are refundable.

How to fix

Check status is SUCCESS before refunding.

12

Over-refunding

Problem

400 exceeds refundable balance.

Why it happens

Sum of refunds exceeded the original amount.

How to fix

Track the remaining refundable balance; cap refunds at it.

13

Assuming a refund webhook exists

Problem

Refund completion never detected.

Why it happens

No dedicated refund webhook is emitted.

How to fix

Poll Refund Status until refund_completed_at is set.

14

Treating INITIATED as paid

Problem

Orders fulfilled that were never completed.

Why it happens

INITIATED is not terminal.

How to fix

Only fulfil on SUCCESS.

15

Expecting PENDING/FAILED status strings

Problem

Status comparisons never match.

Why it happens

GrowthBnk normalises to INITIATED/SUCCESS/FAILURE/DROP/CANCELLED.

How to fix

Compare against the five documented statuses.

16

Tight polling loops

Problem

Rate limited (429) and wasted resources.

Why it happens

Fixed, rapid polling without backoff.

How to fix

Use webhooks primarily; poll with exponential backoff and stop at terminal states.

17

Never stopping polling

Problem

Endless status calls.

Why it happens

No terminal-state check.

How to fix

Stop once status is SUCCESS/FAILURE/DROP/CANCELLED.

18

Ignoring the success flag

Problem

Missing gateway-init failures.

Why it happens

Only the HTTP status was checked; body had success:false.

How to fix

Branch on the success flag as well as the HTTP status.

19

Not handling the status array

Problem

Wrong status read for retried orders.

Why it happens

Transaction Status returns an array (newest first).

How to fix

Use the most recent element for the current outcome.

20

Retrying on timeout without reconciling

Problem

Double charges.

Why it happens

A timed-out payment may have succeeded.

How to fix

Check Transaction Status before retrying a timed-out request.

21

Blindly retrying non-idempotent calls

Problem

Duplicate side effects.

Why it happens

Retries without a stable order id.

How to fix

Keep a unique order id so retries are safe/idempotent.

22

Amount below the minimum

Problem

400 Invalid amount or less than 1 rupee.

Why it happens

Amount was under ₹1.00.

How to fix

Send at least 1.00 with two decimals.

23

Missing customer contact

Problem

Validation error on Initiate Payment.

Why it happens

Neither email nor phone was supplied.

How to fix

Provide at least one of customer_email or customer_phone.

24

Invalid phone format

Problem

Validation rejects the customer phone.

Why it happens

Phone contained non-digits or wrong length.

How to fix

Send digits only, 7–15 characters.

25

Sending amount as a client-supplied value

Problem

Price tampering.

Why it happens

The amount came from the browser.

How to fix

Compute the amount server-side from your order and sign that.

26

No routing rule for the amount

Problem

400 No Routing Rule found for this amount.

Why it happens

No active rule covers the request.

How to fix

Configure a routing rule that covers the amount band.

27

Hardcoding a gateway

Problem

Brittle integration.

Why it happens

Assuming a specific gateway is selected.

How to fix

Let routing choose; never depend on a specific gateway in code.

28

Cancelling a processed transaction

Problem

400 cannot be cancelled.

Why it happens

Only INITIATED transactions can be cancelled.

How to fix

Check status before cancelling.

29

Not whitelisting server IPs

Problem

403 IP is not whitelisted in production.

Why it happens

The calling IP is not on the allow-list.

How to fix

Add your server egress IPs to the whitelist and keep it updated.

30

Calling a disabled module

Problem

403 module access denied.

Why it happens

The module is not enabled on the account.

How to fix

Ask support to enable the module, then retry.

31

Using HTTP instead of HTTPS

Problem

Credentials/requests exposed.

Why it happens

Plaintext transport.

How to fix

Always use HTTPS/TLS for API calls and webhooks.

32

Logging secrets or card data

Problem

Compliance/security exposure.

Why it happens

Salt, full PAN or raw signed requests were logged.

How to fix

Log only IDs and status; redact secrets.

33

Non-constant-time hash comparison

Problem

Timing side-channel on verification.

Why it happens

Used == to compare hashes.

How to fix

Use hash_equals / compare_digest / timingSafeEqual.

34

Localhost webhook URL

Problem

Webhooks never delivered.

Why it happens

The URL is not publicly reachable.

How to fix

Use a public HTTPS URL; use a tunnel for local testing.

35

Assuming webhook ordering

Problem

State machine corrupted by out-of-order events.

Why it happens

Events can arrive out of order.

How to fix

Use timestamps and treat the latest verified terminal state as authoritative.

36

Creating a new HTTP client per request

Problem

High latency and connection churn.

Why it happens

No connection reuse.

How to fix

Reuse one client/SDK instance for the process lifetime.

37

No timeouts on requests

Problem

Threads hang on slow gateways.

Why it happens

Default/no timeout.

How to fix

Set explicit connect/read timeouts and pair with retries.

38

Hardcoding base URLs

Problem

Painful environment switches.

Why it happens

URLs embedded in code.

How to fix

Read the base URL from environment configuration.

39

Committing credentials to git

Problem

Secret leakage.

Why it happens

Keys/salt in source control.

How to fix

Use environment variables / secret managers and gitignore config.

40

Not storing the transaction_id

Problem

Cannot refund or reconcile later.

Why it happens

Only the order id was saved.

How to fix

Persist the GrowthBnk transaction_id with every order.

41

Ignoring request/response IDs

Problem

Slow support resolution.

Why it happens

No traceable identifiers logged.

How to fix

Log request and transaction IDs for every call.

42

No reconciliation job

Problem

Silent mismatches accumulate.

Why it happens

Relying solely on real-time signals.

How to fix

Run a periodic reconciliation against status/settlement data.

43

Swallowing errors silently

Problem

Failures go unnoticed.

Why it happens

Exceptions caught and ignored.

How to fix

Log, alert and surface actionable errors; branch on status/message.

44

Not validating inputs before signing

Problem

Wasted calls and confusing 400s.

Why it happens

Bad data sent to the API.

How to fix

Validate amount, customer and IDs before building the request.

45

Assuming sandbox IDs exist in production

Problem

Lookups fail after go-live.

Why it happens

Environments are isolated.

How to fix

Never hardcode IDs; use IDs from the current environment.

46

Skipping the go-live checklist

Problem

Preventable production incidents.

Why it happens

Rushed launch.

How to fix

Complete the Go Live Checklist before ramping traffic.

47

No monitoring or alerting

Problem

Outages detected late.

Why it happens

No dashboards/alerts on failures.

How to fix

Monitor success rate, webhook delivery and error rates; alert on spikes.

48

Not handling duplicate callbacks

Problem

Double processing.

Why it happens

Callbacks/webhooks can repeat.

How to fix

Deduplicate and make handlers idempotent.

49

Confusing customer_transaction_id with transaction_id in refunds

Problem

Refund fails or targets the wrong record.

Why it happens

The two IDs were mixed up.

How to fix

Use merchant_transaction_id for status/cancel and GrowthBnk transaction_id for refunds.

50

Not testing failure and edge cases

Problem

Breaks in production on the first decline/timeout.

Why it happens

Only the happy path was tested.

How to fix

Test failures, timeouts, pending, refunds and duplicate webhooks in sandbox before go-live.


See also Troubleshooting and the FAQ.