All systems operational200+ sites we watch overReply in under 2h+54 9 11 7820-8554
← Blog

Payment gateway integration developer: how to vet one

For CTOs and engineers choosing who connects their site to payment gateways, CRMs and ERPs: the criteria that matter, from PCI scope to idempotency, plus cost ranges.

werun.dev18 min read
Get a summary withChatGPTClaudeGoogle AI Mode
Bridge of light linking a website window to payment and data nodes, the work of a payment gateway integration developer

Your site has to take payments, push leads into a CRM or read stock from an ERP, and you need to decide who builds that link. The choice matters more than the platform underneath, because an integration touches money and customer data every day it runs. This guide helps you pick the right payment gateway integration developer and check their work before you sign.

The short answer: four kinds of builder can do the job (an in-house engineer, a freelancer, an integration agency or a platform connector app). The right one depends on your payment model, the number of systems involved and who will maintain the code after launch.

It is written for CTOs, engineering leads and technical founders who want to score a candidate against evidence, not a pitch. You get the criteria that separate a safe integration from a fragile one, working code to ask a candidate to explain, and honest ranges for effort.

Key takeaways

  • Choose the payment model (hosted, embedded or custom) before you choose the builder, because it sets your PCI scope and most of the effort.
  • A safe payment integration verifies every webhook signature, stores each event ID and fulfils orders from the verified event, never from the success page.
  • Keep API keys, provider accounts and the repository in your name from day one, and ask for runbooks at handover.
  • Compare quotes by their scope drivers (payment methods, refunds, taxes, field mapping, legacy API quality), not by the headline number.
  • Eight questions, listed near the end, expose inexperience in a single call.

Who can integrate your website with third-party APIs

Four kinds of builder can connect your website to a payment gateway, a CRM or an ERP. Each suits a different situation, and each carries one risk you can check before you commit. Find your situation first, then read the criteria that apply to every option.

Freelancer, agency, in-house or connector app

The cards below place each option by what it suits and what to verify.

Team you already have

In-house engineer

Suits a product you will change for years. Check who covers when that person is away and whether a second engineer reviews payment code.

One bounded job

Freelancer

Suits a single gateway or a single CRM sync. Check availability after launch and ask for a written handover.

Several systems

Integration agency

Suits payments plus CRM plus ERP that must agree with each other. Check that code, accounts and keys end up in your name.

Standard flows

Connector app

Suits common flows on a platform such as Shopify. Check the limits on custom logic, field mapping and monthly fees.

Whichever you choose, the build is a bridge between your site and systems you do not control. Provider outages, API changes and duplicate messages are normal on that bridge, so the builder's job is to make them harmless.

Glowing bridge connecting a browser window to a cluster of nodes, showing a secure link between a website and outside systems
Every integration is a bridge your builder has to keep safe

What each option is good at

An in-house engineer knows your product and your data best. That pays off when the integration changes often, for example when pricing rules or sales stages evolve every quarter. The cost is that one person often holds all the context.

A freelancer is fast and direct for a bounded job. A freelancer can be a sound choice for a single Stripe integration for your website when you have an engineer who can review the code. Without a reviewer, you trust one pair of eyes with your revenue path.

An integration agency brings review, several engineers and cover for holidays. That helps when payments, a CRM and an ERP must agree with each other. A connector app is the quickest route when your flow is standard. It stops being enough when you need rules the app does not expose.

The three jobs hidden in one request

A request such as 'connect Stripe to the site' hides three jobs. A good proposal prices all three:

  • The happy path: the buyer pays and the order is confirmed.
  • The failure paths: declines, refunds, disputes, duplicate messages and provider outages.
  • The operations: monitoring, reconciliation, key rotation and updates when the provider changes its API.

A quote that covers only the first job looks cheap and ends up costing more. Most of the engineering judgment you pay for sits in jobs two and three.

Pick a payment model and PCI scope

Choose the payment model before you choose the builder. It decides how much card data your systems touch, which sets your PCI DSS scope and the compliance work that follows. PCI DSS is the card industry's security standard, maintained by the PCI Security Standards Council, and your provider and acquiring bank tell you which self-assessment questionnaire applies to you.

Payment models and PCI scope

  1. 01Buyer enters cardThe choice of model starts here
  • AHosted checkoutNarrow PCI scope
    1. Provider pageCard goes straight to the provider
    2. Result and tokenAll your server receives
  • BEmbedded fieldsSmall PCI scope
    1. Provider fieldsYour page only hosts them
    2. ProviderCard never reaches your server
  • CCustom handlingWidest PCI scope
    1. Your serverCard passes through your systems
    2. ProviderReceives the card from you

Diagram of three payment models showing where a card number touches your server and how PCI scope widens from hosted to custom

Where the card number travels in each payment model

The diagram shows where a card number travels in each model. The further it enters your own systems, the wider your scope, and the more your team has to prove.

Our pick to start

Hosted checkout

  • Card data path: entered on the provider's page
  • PCI effort: the lightest
  • Design control: branding options only
  • Build effort: days to a couple of weeks

When design pays off

Embedded fields

  • Card data path: provider fields inside your page
  • PCI effort: moderate, your page is in scope
  • Design control: full layout control
  • Build effort: moderate

Rarely justified

Custom card handling

  • Card data path: through your own servers
  • PCI effort: the heaviest, with audits
  • Design control: total
  • Build effort: highest, plus ongoing cost

Hosted checkout: smallest scope

Your buyer pays on a page the provider hosts, then returns to your site. Card data never touches your servers, so the compliance work is the lightest. Stripe Checkout, PayPal and Mercado Pago all offer this model, and a team can ship it in days. Choose it when speed and a small scope matter more than a fully branded payment step.

Embedded fields: more control, moderate scope

Provider-hosted fields sit inside your own page, so the layout feels like yours while the card data still goes straight to the provider. Stripe's Payment Element and similar components work like this. Your scope grows because your page loads the provider's script, so you must protect that page from tampering. Pick it when checkout design clearly affects your conversion.

Custom card handling: rarely worth it

In a custom build, card numbers pass through your servers. You then carry the widest scope, with audits, network controls and logging rules. Few online stores gain enough to justify it. If a candidate proposes it as the default, ask which requirement forces it.

What to ask about your PCI questionnaire

Ask the candidate which model they propose and which questionnaire it implies for you. A confident answer names the model, says what stays on your side (for example, protecting the checkout page and keeping the provider's script current) and points to your provider's guidance. Be careful with anyone who says 'PCI is handled' without naming the model.

The same questions apply to Adyen, PayPal, Mercado Pago and Redsys, which follow the same patterns. For local methods and regional gateways, the post on web development for fintech and digital payments in LATAM adds context.

Webhooks, retries and idempotency that protect revenue

Fulfil orders from a verified provider event, never from the page the buyer lands on. A webhook is a message the provider sends to your server when something happens, such as a payment succeeding. Done well, it keeps your orders correct when networks fail, buyers close tabs and providers retry.

Why it matters

The browser redirect is not proof of payment. A buyer can close the tab before the success page loads, or open that URL without paying. Fulfil orders from the verified webhook event.

This is the lifecycle to expect for every payment event: verify, deduplicate, acknowledge, process and reconcile.

Webhook lifecycle

  1. 01Provider sends eventPayment succeeded, signed by provider
  2. 02Verify signatureChecked against the raw body
  3. 03Look up event IDRepeat events are skipped
  4. 04Store ID, reply 200Provider stops retrying
  5. 05Worker fulfils orderRuns apart from the reply
  6. 06Order confirmedNightly check catches any gap

Diagram of the webhook lifecycle: verify signature, check event ID, acknowledge, process by worker, skip duplicates and reconcile nightly

A payment event from provider to fulfilled order, with duplicates skipped

Verify the signature on the raw body

Anyone can post JSON to a public URL. The signature header lets your server prove that the message came from the provider. It is computed over the exact bytes sent, so the route must read the raw body before any JSON parsing. A common bug is a global JSON parser that changes the bytes and makes every check fail, and the usual wrong fix is switching the check off. The Stripe webhooks documentation describes the scheme in full.

The sample below uses TypeScript, Express, the official stripe package and PostgreSQL. The pattern is the same for other providers.

import express from 'express';
import Stripe from 'stripe';
import { Pool } from 'pg';

// Schema (run once):
// CREATE TABLE processed_events (event_id text PRIMARY KEY, type text NOT NULL, received_at timestamptz NOT NULL DEFAULT now());
// CREATE TABLE jobs (id bigserial PRIMARY KEY, kind text NOT NULL, payload jsonb NOT NULL, created_at timestamptz NOT NULL DEFAULT now());

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET!;
const db = new Pool({ connectionString: process.env.DATABASE_URL });
const app = express();

// The raw body is required: the signature covers the exact bytes Stripe sent.
app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), async (req, res) => {
  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(
      req.body,
      req.headers['stripe-signature'] as string,
      endpointSecret
    );
  } catch {
    // Bad signature or altered body: reject and do nothing else.
    return res.status(400).send('Invalid signature');
  }

  const client = await db.connect();
  try {
    await client.query('BEGIN');

    // The primary key on event_id turns a duplicate delivery into a no-op.
    const inserted = await client.query(
      'INSERT INTO processed_events (event_id, type) VALUES ($1, $2) ON CONFLICT (event_id) DO NOTHING',
      [event.id, event.type]
    );

    if (inserted.rowCount === 0) {
      await client.query('ROLLBACK');
      return res.status(200).send('Duplicate ignored');
    }

    // Queue the slow work for a worker instead of doing it inside the request.
    if (event.type === 'payment_intent.succeeded') {
      const intent = event.data.object as Stripe.PaymentIntent;
      await client.query('INSERT INTO jobs (kind, payload) VALUES ($1, $2)', [
        'fulfil_order',
        JSON.stringify({ orderId: intent.metadata.order_id }),
      ]);
    }

    await client.query('COMMIT');
    return res.status(200).send('ok'); // Answer fast.
  } catch (err) {
    await client.query('ROLLBACK');
    return res.status(500).send('Retry later'); // The provider will retry.
  } finally {
    client.release();
  }
});

// Outgoing request: the same key always returns the same result,
// so a retry after a timeout cannot create a second charge.
export async function createPayment(orderId: string, amountCents: number) {
  return stripe.paymentIntents.create(
    { amount: amountCents, currency: 'usd', metadata: { order_id: orderId } },
    { idempotencyKey: `order-${orderId}-payment` }
  );
}

app.listen(3000);

Store the event ID to ignore duplicates

Providers deliver at least once, so the same event can arrive twice. The handler inserts the event ID into a table with a unique constraint. If the insert conflicts, the event is a duplicate and the handler acknowledges it without repeating the work.

In the sample, the insert and the job creation share one transaction, so a crash cannot leave an event marked as processed with no job. The handler answers 200 quickly and a worker does the slow part, such as sending the order to your ERP. If you also process events with automation, the post on webhooks and AI integrations as data pipelines shows how to design the next step.

Idempotency keys on outgoing requests

Duplicates also happen in the other direction. A timeout leaves you unsure whether a charge went through. An idempotency key is a unique value you send with a request, so the provider returns the original result instead of creating a second charge.

Derive the key from something stable, such as the order ID, as the createPayment function above does. Stripe documents how long it keeps keys and what happens when the same key arrives with different parameters.

Reconcile against the provider daily

Webhooks can still be missed, for example during your own outage. A nightly job lists the provider's payments for the last day and compares them with your orders. Anything paid at the provider and missing in your store gets flagged or repaired automatically.

Ask a candidate how they would detect a missed event. If the answer is 'the customer would write to us', the design is incomplete.

API authentication, rate limits and monitoring

The same care applies to CRM, ERP and shipping APIs, where the usual risk is a leaked key, a broken sync or a silent failure rather than a card breach. A reviewer should recognise the categories in the OWASP API Security project, especially broken authorization and unrestricted resource consumption.

Keep secrets and scopes tight

Secrets belong in environment variables or a secrets manager, never in the repository, a front-end bundle or a chat message. Use separate keys for test and live, and give each key only the permissions it needs. Stripe's restricted keys and OAuth scopes on a CRM both allow this. If a key leaks, a narrow scope limits the damage and rotation is a routine task.

Check also that your server decides who may read which record. Broken object-level authorization, where one customer reads another's data by changing an ID, appears first in the OWASP API Security Top 10.

Backoff and queues for rate limits

Every API limits how fast you can call it. When you pass the limit, the API answers with HTTP 429 and often a Retry-After header. A good integration waits, retries with exponential backoff and random jitter, and puts non-urgent work in a queue so a burst of orders cannot flood the API.

The same patterns apply to AI providers, as the post on handling LLM API rate limits in production shows. Ask the candidate what happens to 5,000 queued updates after a one-hour outage. A good answer covers ordering, retries and a limit on how fast the backlog drains.

Alerts that reach a person

Silent failure costs the most: orders that never reach the ERP, leads that never reach the CRM. Monitoring should track failed jobs, webhook error rates and the age of the oldest queued item, then alert a named person or channel. A dashboard nobody opens does not protect you. Agree up front who receives the alert, what counts as urgent and how fast someone answers.

Cost and timeline of a payment gateway integration

Quotes vary widely because scope varies widely. The ranges below are illustrative, drawn from typical scoping conversations rather than a survey or a price list. Use them to sanity-check a quote, then ask the builder to show which drivers explain their number.

IntegrationIllustrative timelineMain drivers
Hosted checkoutAbout 1 to 2 weeksOne gateway, few payment methods, simple refunds
Embedded payments with subscriptionsAbout 3 to 6 weeksPayment methods, proration, taxes, failed-payment retries
CRM syncAbout 2 to 5 weeksField mapping, duplicate handling, one-way or two-way sync
ERP integrationAbout 6 to 12 weeks or moreLegacy API quality, test environments, data cleanup

Payment gateway: what drives the range

Weeks grow with the number of payment methods, partial refunds, taxes, currencies and subscriptions. Each adds states your handler must track. A candidate who asks about these in the first call is scoping honestly. The phases below show how a mid-sized embedded integration might run.

  1. Week 1 (illustrative)

    Scoping and sandbox

    Agree payment model, methods and events. Connect a test account and confirm the data path.

  2. Weeks 2 to 3

    Build and webhook handling

    Build the checkout, the signed webhook endpoint, the event table and the worker.

  3. Week 4

    Test the failure cases

    Replay duplicates, simulate declines, refunds and a provider outage, and review the alerts.

  4. Week 5

    Go live and reconcile

    Switch to live keys, watch the first orders and run the first daily reconciliation.

Testing the failure cases deserves its own week, because that is where cheap quotes cut corners.

CRM sync: field mapping is the work

The API call that creates a contact is easy. The work is deciding what a lead is, which system wins when two values disagree and how to avoid duplicates. Effort follows the number of fields, objects and sync directions. A one-way form-to-CRM flow is quick, while a two-way sync with deal stages takes longer.

ERP: legacy constraints and testing

ERP projects take longest because the other side sets the pace: older APIs, batch-only exports, limited test environments and data that needs cleaning. Budget time for a sandbox you can break, and for a plan that keeps stock, price and order data in step. The post on API and legacy system integrations for enterprise websites goes deeper into this case.

Whatever the system, ask for a fixed-scope discovery phase first. The estimate for the build then rests on what was learned, not on a guess.

Who owns the integration after launch

You should own every account, key and line of code the integration uses, from the first day. Ownership turns a change of builder into a handover instead of a rescue. It is also the simplest test of a partner's confidence in their own work.

Accounts and keys in your name

Create the payment, CRM and ERP accounts yourself, and invite the builder as a user with limited permissions. The builder generates restricted API keys inside your accounts, and you can revoke them whenever you wish. Be wary of arrangements where the builder's merchant account processes your payments, because your history and settlements cannot move with you.

Code, docs and runbooks you receive

At handover you should hold:

  • The repository in your own organisation, with full history.
  • A README with setup steps and every environment variable named.
  • A list of the webhook events handled and what each one does.
  • A runbook for common failures, such as a stuck queue or a missed event.
  • Tests that cover the failure paths, and a diagram of the data path.

Maintenance when providers change their API

Providers deprecate API versions, rotate certificates and change webhook payloads. Someone must read those notices and test the changes. Decide whether your team, the original builder or a maintenance plan covers it, and write it into the agreement. At werun.dev that is what the Care plan and the monthly Retainer are for, and code and accounts stay in your name either way.

Vet a payment gateway integration developer

You can judge a candidate in one or two calls if you know what to listen for. Use the red flags to screen proposals and the questions to test experience.

Red flags in a proposal

  • They ask for your secret API key by email or chat, or want to use their own merchant account.
  • Orders are fulfilled on the success page, with no webhook.
  • The quote is a single line with no mention of refunds, disputes or retries.
  • Card numbers or full request bodies end up in logs.
  • Test and live keys share one configuration, or there is no test plan.
  • The code lives only in the builder's repository, with no handover terms.
  • PCI is 'handled' with no payment model named.

Questions that reveal real experience

Ask these and listen for specifics: named events, named tables, named failure cases. Treat the list as a scorecard, with one point for each concrete answer.

  • Who holds the API keys and the merchant account, and where do the keys live?
  • Which payment model do you propose, and what does it mean for our PCI questionnaire?
  • How do you verify webhook signatures on the raw body?
  • How do you handle a duplicate or out-of-order event?
  • Which idempotency key do you send on a charge and on a refund?
  • What happens when we hit a rate limit, or the provider is down for an hour?
  • Who gets the alert at 3 a.m. and how do you detect a missed event?
  • What do we receive at handover: repository, docs, runbooks and tests?

A candidate who has done this before answers most of these without hesitation, and often adds a story about a time it went wrong. That story is useful evidence.

Where to start this week

Write a one-page integration brief before you talk to anyone. List the systems involved, the events that move between them (order paid, refund issued, contact created, stock changed) and which system is the source of truth for each. Add the payment methods you need, the countries you sell in and who will own the integration afterwards.

That page lets any candidate give a comparable quote, and it shows you quickly who asks good questions. Take the checklist above to two or three calls and compare the answers.

If you want a second pair of eyes, tell us your goal. werun.dev builds payment, CRM and ERP integrations with code, accounts and keys in your name, and we reply in under 2 hours on business days. Send us the brief and we will tell you which payment model and timeline we would propose.

Frequently asked questions

Who can integrate my website with a payment gateway?

An in-house engineer, a freelancer, an integration agency or a platform connector app can all do it. Pick by the number of systems, the payment model and who will maintain the code afterwards. Whoever you choose should work in accounts you own and hand over code and documentation.

How much does a payment gateway integration cost?

It depends on scope more than on the gateway. A hosted checkout takes roughly 1 to 2 weeks of work, while embedded payments with subscriptions, taxes and refunds often take several weeks more (illustrative ranges). Ask for a quote broken down by payment methods, refunds, taxes and testing.

Is hosted checkout or embedded payment better for PCI compliance?

Hosted checkout keeps card entry entirely on the provider's page, which gives the smallest PCI scope. Embedded fields also send card data straight to the provider, but your page loads the provider's script, so your responsibilities grow slightly. Confirm the questionnaire that applies with your provider.

What is an idempotency key in payment integrations?

An idempotency key is a unique value sent with a request so that retrying it returns the original result instead of repeating the action. For payments, it prevents double charges after a timeout. Build it from a stable identifier such as the order ID.

How long does an ERP or CRM API integration take?

Illustrative ranges are about 2 to 5 weeks for a CRM sync and 6 to 12 weeks or more for an ERP. The time goes into field mapping, legacy API limits, test environments and data cleanup rather than into the API calls themselves.

What should I ask before I hire an API integration developer?

Ask who holds the keys, which payment model they propose, how they verify webhook signatures, how they handle duplicates and rate limits, who receives alerts and what you get at handover. Specific answers show real experience.

Running into this on your own stack?

Tell us the platform and the problem. We'll tell you what it takes and who does it.

No commitment. Just a conversation.