Payment Gateway Integration: Methods, PCI Scope, and Cost
Payment gateway integration is more than dropping in an API. Here's how the methods differ, how each sets your PCI DSS scope, the architecture for reliable payments, and what it costs.

Payment gateway integration is the work of wiring a payment gateway into your product so it can take money reliably, and it is rarely the one-afternoon job the vendor docs make it look like. The API call that charges a card is the easy part. What surrounds it is the real engineering: choosing an integration method that sets how much of the PCI DSS standard you answer for, designing a payment flow that never double-charges when the network hiccups, verifying webhooks, reconciling your books daily, and handling the long tail of declines, timeouts, and 3-D Secure challenges. Get the method wrong and you inherit a compliance program you did not need; get the architecture wrong and you lose or duplicate money live.
Most explainers of payment gateway integration are marketing for a specific gateway: they list the methods and stop, without comparing them or explaining how each changes your PCI footprint. This guide covers the parts those pages skip, in the framing we use to scope and build one.
What payment gateway integration is, and how it differs from building a gateway
Payment gateway integration means connecting an existing payment gateway to your application so it can authorize, capture, and report on transactions, without you running the card-network machinery. You are the merchant; the gateway is the service that talks to the processors and the card networks; integration is the wiring between your checkout, your backend, and that service.
The distinction that trips people up is integration versus building a gateway. Payment gateway development, building one from scratch, means becoming the thing that connects directly to acquirers and card networks, holds the certifications, and runs the fraud and routing engines, which almost no product needs and which makes sense only for payment companies whose core product is the gateway itself. For everyone else, the smart version of the job is building the right logic around a gateway you did not write.
What is a payment gateway
A payment gateway is the service that takes a customer's card details, encrypts them, and passes the transaction to the banking networks for an approve-or-decline decision. It sits between your checkout and the acquiring bank, so your systems never speak the low-level protocols those networks use. In practice most teams reach a gateway through a provider that bundles more than raw connectivity: tokenization so you store a reference instead of a card number, fraud screening, a dashboard, and webhooks that tell you what happened after the sale.
How a payment flow works end to end: authorization, capture, settlement
A payment flow runs in three distinct phases that behave very differently: authorization checks and holds the funds, capture tells the bank to take them, and settlement is the later batch transfer of money into your account. Treating these as one step is the source of a surprising number of payment bugs, because each phase can succeed or fail on its own, and the gaps between them are where money goes missing if you are not tracking state.
Authorization is the real-time check. Your server asks the gateway to verify the card and place a hold for an amount, the request reaches the issuing bank, and you get back an approve or decline in roughly a second. An approval is a promise, not a transfer: the funds are reserved but no money has moved yet. Capture is the instruction to collect on that promise. Most checkouts capture immediately, but you can authorize now and capture later, the shipped-goods or hotel-style flow: confirm the card at order time, take the money at fulfillment. An uncaptured authorization eventually expires and releases the hold.
Settlement is the part that confuses founders because it runs on bank time, not internet time. Your application sees an approved capture instantly, but captured transactions are batched, usually daily, and the funds take a day or more to land in your acquiring account, net of fees and sometimes net of reversals. This delay is why the ledger and reconciliation below matter: "the gateway said yes" and "the money is in our account" are different events on different clocks, and a correct system records both. Refunds and chargebacks ride the same rails in reverse on their own schedule, so any model that treats a payment as one instantaneous event misreports your real position.
Hosted vs API vs direct integration: an engineering trade-off table
The three integration methods (hosted, embedded API, and direct API) trade design control against compliance weight and engineering effort almost linearly, and picking among them is the most consequential early decision in any payment gateway integration. The table lays the trade-offs side by side.
| Method | PCI scope | UX control | Build effort | Failure modes | Best for |
|---|---|---|---|---|---|
| Hosted / redirect page | Smallest; card data never hits your servers | Low; provider owns the card screen | Lowest; wire a redirect and handle the return | Redirect drop-off, return-URL tampering, lost session on return | Getting to revenue fast, low-volume or content-led products |
| Embedded fields / iframe (tokenization) | Reduced; provider iframe collects the card, you get a token | High; your page, provider's secure field | Moderate; client SDK plus server-side charge on a token | Token expiry, script-load failures, 3DS handoff inside your page | Most SaaS and marketplace checkouts wanting a native feel |
| Direct API (card data on your server) | Full program; you touch raw card data | Total; you control every pixel and byte | Highest; you build and certify card handling | Anything above, plus card-data exposure and the full breach surface | Payment companies and platforms with a real reason to hold card data |
These methods form a ladder, and you want the lowest rung that still meets your product needs. Embedded fields are the default for products that want their own branded flow without owning card data, since the provider's iframe collects the sensitive number while your page owns everything around it. Direct API is a deliberate, heavy choice you make only with a concrete reason and the team to support it. Almost every "we need full control" instinct is satisfied by embedded fields at a fraction of the compliance cost.
How your integration method sets your PCI DSS scope
Your integration method is the single biggest factor in how much of the PCI DSS standard you must comply with, because PCI scope follows the card data and each method routes that data differently. The Payment Card Industry Data Security Standard, published by the PCI Security Standards Council, defines Self-Assessment Questionnaire (SAQ) types that match different ways a merchant takes payments. Which SAQ applies is decided by your architecture, not your intentions, so the method you pick effectively chooses your compliance burden.
The methods map straight onto the questionnaires. A fully hosted or redirect integration, where card data never reaches your servers, corresponds to SAQ A, the smallest scope, because you have outsourced all handling and storage of card data. An embedded approach that tokenizes the card inside the browser corresponds to SAQ A-EP, a middle tier that still pulls your web page into scope because your site controls the page that loads the payment field. A direct API integration that collects card data on your own server lands you in SAQ D, the full program. The current version of the standard is PCI DSS v4.0.
| Integration method | SAQ level | What touches your servers |
|---|---|---|
| Hosted page or redirect | SAQ A | Nothing card-related; the provider hosts card entry end to end |
| Embedded iframe or JavaScript tokenization | SAQ A-EP | Your page that loads the payment field, but not the raw card number |
| Direct API collecting card data | SAQ D | The full card number and account data, in transit and at rest |
The lesson that saves the most money and risk: keep the card number out of your systems and your PCI scope collapses. There is rarely a product reason to accept SAQ D, and the gap between A-EP and D is enormous in audit effort, in the controls you must run, and in the breach surface you expose, so our default is to architect every integration so the raw card never lands on a server we control. One point on language, because it is frequently muddled: as an engineering partner we build to PCI DSS v4.0, implementing the controls and producing the evidence an assessment needs, but we cannot hand you a certification. You achieve that with your own assessors; anyone claiming to make you "PCI certified" on your behalf is blurring a line that matters.
Designing a reliable integration: payment state machine, idempotency keys, and the outbox pattern
A reliable payment integration is built on three load-bearing pieces: an explicit payment state machine, idempotency keys that make retries safe, and the outbox pattern that keeps your database and the gateway from drifting apart. Payments are distributed-systems problems wearing a checkout's clothing: the network can fail at the worst moment, after the gateway processed the charge but before you learned the result, and a system that does not plan for that ambiguity will eventually take money it cannot account for.
Start with the state machine. A payment is not a boolean, it is a lifecycle, and modeling it as an explicit set of states with allowed transitions is what keeps it correct. A workable set is created, authorized, captured, failed, refunded, and a deliberate requires_action for flows that bounce into a 3-D Secure challenge. Every transition is driven by a concrete event, an API response or a webhook, and illegal transitions are rejected rather than silently applied. When a payment is stuck, the state tells you exactly where it stopped.
Idempotency keys are how you make retries safe. Every request that moves money carries a unique key you generate, and the gateway uses it to guarantee the operation runs once even if it arrives twice. The scenario this defends against is common: your charge call times out, you do not know whether it went through, so you retry, and without a key you have just charged the same payment twice. With the key, the second request returns the result of the first, so no money-moving call should leave your systems without one.
The outbox pattern solves the dual-write problem, the quiet killer in payment systems. You need to both update your database (mark the order paid) and trigger an external action (call the gateway, or publish an event), but with no shared transaction across a database and an external API, a crash between the two leaves them inconsistent. The outbox fixes this by writing the intent to an outbox table inside the same database transaction as your business change, so either both commit or neither does, and a separate worker reads the outbox and performs the external call, retrying until it succeeds. Your database stays the source of truth, and combined with idempotency keys this lets a payment survive a crash at any point without losing or duplicating money.
| Stage | Responsibility |
|---|---|
| Checkout / tokenize | Browser collects the card in the provider's secure field and returns a token; no raw card reaches your server |
| Server with idempotency key | Records payment intent and the idempotency key inside one DB transaction that also writes the outbox row |
| Gateway API call | A worker reads the outbox, sends the tokenized charge with the idempotency key, and handles the response |
| Webhook verify | Verifies the signed event from the gateway and advances the payment state machine |
| Ledger / reconciliation | Posts the confirmed movement to an append-only ledger for daily reconciliation against gateway reports |
This is not theoretical. On Chaindoc, an eIDAS-qualified e-signature platform, we wired Stripe Connect so an agreement, a KYC identity check, and payment collection close inside one regulated flow, where an authorization, a payout to the right party, and an identity verification all have to agree and survive failures without leaving the document in an ambiguous state. The state machine, idempotency, and outbox discipline above are what make a flow like that auditable instead of fragile, and the same patterns underpin any custom software development where correctness under failure is the requirement.
Webhooks done right: signature verification, retries, and out-of-order events
Webhooks are how a gateway tells your system about things that happen after, or outside of, your original request: an HTTP call to your server reporting that a payment captured, a dispute opened, or a payout settled. Handling them correctly means verifying every signature, treating delivery as at-least-once, and never assuming events arrive in order, because the naive handler that trusts the payload and processes it once is wrong in three ways, each of which has bitten teams in production.
Verify the signature first, before you read the body as truth. A webhook endpoint is a public URL anyone can POST to, so an unverified handler that marks an order paid on receipt is a forgery waiting to happen. Gateways sign each event with a secret shared only with you, and your handler must recompute that signature over the raw request body and compare it before doing anything else.
Then treat delivery as at-least-once and make your handlers idempotent. Gateways retry webhooks until they get a success response, so network blips cause the same event to arrive more than once, and a handler that is not idempotent will ship the order or credit the wallet twice. The fix is to record each processed event ID and ignore repeats, so the second delivery is a no-op. Finally, expect events out of order: a captured event can land before the authorized event that logically precedes it. This is why the state machine matters: rather than blindly applying whatever arrives, you check whether the transition is legal from the current state and hold or reconcile anything early.
The teams that get payments right treat the gateway call as the easy hour and spend their effort on the reconciliation, the idempotency, and the question of who owns each failure. The charge succeeds in a second. Making sure your books and the bank agree to the cent every day is the actual build.
Reconciliation and ledgering: matching payment gateway events to your records
Reconciliation is the daily discipline of proving that your records and the gateway's records agree to the cent, and it rests on keeping an append-only ledger as your internal system of record for money. Your application database tracks orders and payment states, but it is not a financial ledger, and treating it as one is how discrepancies hide until an audit drags them out. A ledger is a separate record where every money movement is an immutable entry: you never update or delete a financial fact, you only append corrections, which is what makes the books auditable.
The job itself is simple but essential. Gateways publish daily settlement files or an API that lists every charge, refund, fee, and payout. Every day, an automated process pulls that report and matches it line by line against your ledger, with three possible outcomes. Matched entries confirm the world is consistent. Entries in the gateway report missing from your ledger usually mean an event you failed to record, often a missed webhook, which is why webhook reliability and reconciliation are two halves of one system. Entries in your ledger missing from the gateway, or amounts that disagree, point to a bug or a timing gap that needs a human. Because of the settlement delay, timing mismatches are normal at the boundaries of a day and should be expected, not flagged as errors.
What makes this robust is automating the match and escalating only the exceptions. A reconciliation a person runs by hand once a month silently breaks, the discrepancy weeks deep before anyone looks; a job that runs every day, auto-clears the matches, and surfaces only the unmatched lines turns reconciliation from a periodic panic into a quiet background check. Fees matter here too: the gateway's payout is net of its fees, so your ledger has to model gross charge, fee, and net settlement separately, or your revenue numbers will never tie out.
Error handling and retries: hard vs soft declines, timeouts, and 3-D Secure
Good payment error handling starts by separating declines you should never retry from ones you safely can, then layers in disciplined timeout handling and the 3-D Secure challenge flow. Most teams treat "the payment failed" as a single case, giving up too early on recoverable failures or hammering the gateway on permanent ones; the taxonomy is what makes the response correct.
A hard decline is permanent: the issuer is refusing this card for a reason that will not change on retry, such as a stolen-card flag, a closed account, or an invalid number. Retrying is pointless and can look like abuse to the networks, so the right response is to stop and ask for a different method. A soft decline is temporary: insufficient funds right now, a transient issuer error, a velocity limit. These can succeed on a later attempt, so they are candidates for a retry after a delay. The two come through in the gateway's response codes, and mapping each code to hard or soft is the first job of any decline handler. Subscriptions lean on this heavily: a smart retry schedule on soft declines recovers real revenue that a naive "cancel on first failure" would lose.
Timeouts are the genuinely hard case because they leave you in an ambiguous state: the request did not return, and you do not know whether the gateway processed the charge or never received it. Here the earlier patterns earn their keep. You retry with backoff, you carry the same idempotency key so a retry of an actually-processed charge returns the original result instead of double-charging, and you let your state machine hold the payment as pending until a webhook or a status query resolves the truth. Never assume a timeout means failure or success, because either guess takes or loses money. Then there is 3-D Secure, the issuer-driven step-up that asks the cardholder to confirm with a code or a banking-app approval. When the gateway signals that a charge requires authentication, your flow moves the payment to requires_action, hands the customer to the challenge, and resumes on the result. Under European PSD2 strong customer authentication this step is mandatory for many transactions, one more reason to build the challenge path as a first-class part of the flow.
| Error class | What it means | Correct response |
|---|---|---|
| Hard decline | Permanent issuer refusal (stolen, closed, invalid) | Stop, ask for a different method, do not retry |
| Soft decline | Temporary (insufficient funds, transient issuer error) | Retry after a delay, with backoff for subscriptions |
| Network timeout | Unknown whether the charge processed | Retry with the same idempotency key; hold state until resolved |
| Requires 3DS | Issuer demands strong customer authentication | Move to requires_action, run the challenge, resume on result |
The payment gateway API in practice: keys, a minimal server-side charge, tokenization
Working with a payment gateway API in practice comes down to three habits: handle your API keys like the secrets they are, always tokenize the card on the client and charge on the server, and treat test and live environments as strictly separate worlds. The API itself is usually small and clean; the discipline around it keeps you secure and your scope minimal.
API keys come in pairs. You get a publishable key that is safe to expose in the browser, used only to tokenize a card, and a secret key that lives exclusively on your server and can move money. The secret key never appears in client code, a repository, or a log line, and it is loaded from a secrets manager at runtime. Providers issue separate test and live key sets, and keeping them apart prevents the bad day where a test charge hits a real card or a live charge vanishes into the sandbox. Keys should also be rotatable: on a schedule, and immediately if one is exposed.
The charge sequence that keeps your PCI scope small is always the same shape across providers. On the client, the customer enters their card into the provider's secure field, the provider tokenizes it in the browser, and your page receives a token that stands in for the card, so the raw number never reaches your server and only that token goes to your backend. On the server, your code calls the gateway with the secret key, the token, the amount, the currency, and a fresh idempotency key, and the gateway returns an authorization or charge result you record against your state machine. Tokenization is the linchpin: because you store and pass a token, you can charge a returning customer, issue a refund, or run a subscription without ever holding the sensitive data, and your servers stay out of the heaviest part of PCI scope.
How to build a payment gateway
When teams ask "how to build a payment gateway," they almost always mean building the payment logic around a gateway, not building one from scratch, which is a payment-company undertaking very few products should attempt. What you actually build is the layer that makes a third-party gateway reliable inside your product: the tokenized checkout, the server-side charge with idempotency, the payment state machine, the webhook handlers, the ledger and reconciliation, and the decline and 3DS handling. That is the buildable, valuable work this guide lays out.
Testing the integration and going live: sandbox, a declined-card and 3DS matrix, and the checklist
Testing a payment integration means driving every branch in the gateway's sandbox before any real money moves, then working a go-live checklist that confirms the operational pieces are in place. The sandbox is the provider's full-fidelity test environment, reachable with your test keys, and it gives you special card numbers that deterministically trigger specific outcomes: a clean approval, a particular decline, a card that demands 3-D Secure. The point is not to confirm the happy path works once, it is to prove the unhappy paths behave correctly, because that is where production payment systems actually break.
Build an explicit test matrix and run every row, as the table below lays out. An approved charge advances to captured and posts to the ledger; a declined card maps to the right hard or soft category and stops or queues a retry; a 3DS-challenge card moves to requires_action, runs the challenge, and resolves on both success and abandonment; a simulated timeout proves your idempotency key prevents a double charge; a duplicate submit yields exactly one charge. Webhooks get their own testing: trigger events in the sandbox, confirm signature verification rejects a tampered payload, and confirm a replayed event is a no-op.
| Test case | Expected behavior |
|---|---|
| Approved card | State advances to captured; ledger entry posted |
| Declined card | Mapped to hard or soft; stop or retry accordingly |
| 3DS challenge | Moves to requires_action; resolves on success and on abandonment |
| Network failure / timeout | Retry with idempotency key yields one charge, not two |
| Duplicate submit | Exactly one charge despite repeated submission |
Going live is its own checklist, and it is where avoidable launch incidents come from. Confirm the merchant account and acquiring relationship are active, not just the gateway test account. Swap test keys for live keys and verify nothing still points at the sandbox. Register your production webhook endpoints and re-verify signatures against the live signing secret, which differs from the test one. Stand up monitoring and alerting on payment failures, webhook processing, and reconciliation mismatches before the first real charge, not after the first incident. Run a small real transaction end to end, including a real refund, to prove the full loop, and confirm the reconciliation job is scheduled with someone owning the exceptions it surfaces. Shipping without this operational layer means discovering the gaps with real customers and real money, the most expensive way to find them.
What integration costs and how to scope it
Payment gateway integration cost tracks how much of the stack you take on, so the honest way to talk about it is in scope tiers rather than a single number. A single hosted gateway, an embedded API integration with its own state machine and reconciliation, and a multi-gateway orchestration layer that routes and fails over across providers are three different undertakings, each adding surface area, edge cases, and a different team shape. The table frames them as effort and timeline rather than invented figures, because a real number only comes from scoping your actual flow.
| Scope tier | What you build | Timeline and team shape |
|---|---|---|
| Single hosted gateway | A redirect or drop-in checkout on one provider, with webhooks and reconciliation | Weeks; a small senior effort |
| Embedded API on one provider | Tokenized checkout, payment state machine, idempotency, full test matrix | A longer window; a senior squad with compliance input |
| Multi-gateway orchestration | A routing and failover layer over several providers, with per-provider reconciliation | Multi-month; a standing team with reliability and reconciliation focus |
The biggest cost lever is the same one that drives the architecture and the PCI scope: how much you own. A single hosted gateway stays cheap because the provider carries the heavy parts. An embedded API integration costs more, with more of your own code to harden and more PCI surface to manage, and it is the tier most growing SaaS products live in. The orchestration tier is where cost rises sharply, and you reach for it for concrete reasons: routing payments by cost or region, redundancy so one provider's outage does not stop revenue, or operating across markets where different providers win in different countries. We built exactly this for Swissy, a crypto wallet whose fiat on-ramp selects the payment provider by the user's location and currency, behind one consistent flow. That is multi-gateway integration earning its cost, not gold-plating; for most products the right move is to start at the lightest tier and climb only when volume, geography, or reliability genuinely demand it. The mechanics of pricing a build like this are laid out in our custom software development cost guide, the integrate-or-build call in build versus buy for software, and where payments sit inside a larger financial product in our embedded finance guide. When you are ready to turn this into a plan, a scoped discovery against our fintech and custom software development teams sets the PCI scope and architecture correctly from day one.
Frequently asked questions
A payment gateway is the service that captures a customer's card details, encrypts them, and passes the transaction to the banking networks for authorization. It sits between your checkout and the card processors, returning an approve or decline result and shielding you from the raw card number. Most teams reach a gateway through a provider that also bundles tokenization, fraud screening, and webhooks.
A hosted gateway moves the card entry onto the provider's own page or iframe, so card data never touches your servers and your PCI burden drops to the lightest questionnaire. An integrated gateway collects card details inside your own checkout and sends them through the gateway API, which gives you full control of the experience but pulls more of your systems into PCI scope. It is a direct trade between design control and compliance weight.
A single hosted or drop-in integration on one provider, with webhooks and reconciliation wired up, is usually a matter of weeks. An embedded API checkout with tokenization, a payment state machine, and a full test matrix runs longer. A multi-gateway setup with routing and failover is a multi-month build. The gateway call is quick; the reliability, reconciliation, and edge-case handling around it are what set the real timeline.
Yes, the method you choose is the single biggest lever on PCI DSS scope. The PCI Security Standards Council ties your obligations to how card data flows: a hosted or redirect page keeps card data off your servers and maps to the smallest self-assessment, an embedded iframe or tokenized field maps to a middle tier, and collecting raw card data on your own server pulls you into the full program. Keeping the card number out of your systems is the cleanest way to shrink scope.
Yes, and many products do once a single gateway stops being enough. You wrap each gateway behind one internal payment interface, then add a routing layer that picks a provider by cost, region, currency, or health, and fails over when one returns errors. It adds real work in reconciliation, since every provider reports differently. We built exactly this for a wallet whose fiat on-ramp selects the payment provider by the user's location and currency.
Cost tracks the scope you take on rather than a fixed price. A single hosted gateway is the lightest build, a small senior effort over weeks. An embedded API integration on one provider, with tokenization and a payment state machine, is a larger piece of work over a longer window. A multi-gateway orchestration layer with routing and failover is a multi-month program. A scoped discovery against your real flow is the only way to turn this into a firm number.
More from the journal

Payment Processing Software: How It Works and How to Build It
Payment processing software is the engine that moves money for merchants. Here's how authorization, clearing, and settlement work, the ledger and reconciliation underneath, the PCI scope, and build vs buy.

Loan Management Software: How It Works and How to Build It
Loan management software runs a loan from origination through servicing to payoff. Here's the lifecycle as a system, the servicing and amortization engine, the compliance you build in, and build vs buy.

Embedded Finance: How It Works and How to Build It
Embedded finance puts banking, payments, and lending inside non-financial products. Here's how it works, what it costs to build, and the architecture and compliance behind it.