Custom API integration and webhooks
Almost anyone can stand up an integration that works on day one. The hard part is that it still works on the day the other end takes ten seconds to answer, returns an error halfway through a batch, or resends the same event three times.
The integration is fine, except that every couple of weeks somebody asks about an order that never arrived. Nobody can answer without opening the database, because there is no single place to look up what happened to that one message.
Why a no-code tool isn't always enough
Visual automation platforms handle 80% of cases very well, and we use them daily. They stop being enough in three specific situations: when the volume makes the per-execution price stop making sense, when you need a real transaction spanning two steps, and when the error logic is more complex than the business logic. That last one is more common than it sounds — what takes time to build is never the happy path, it is everything else. The right answer is rarely everything custom: it is usually leaving in the tool what belongs there and pulling into code the two or three pieces that overflow it.
The flows that have to be solved
Each one with the design decision that determines whether it survives production.
At-least-once delivery, exactly-once processing
Practically no webhook sender guarantees single delivery. What you build on the receiving end is the ability to recognize a repeated event and discard it, storing the event key alongside the operation in the same transaction.
Without that, one retry from the sender produces a duplicate charge, a duplicate order or an email sent twice. And senders retry more times than you expect them to.
Receive fast, process later
The endpoint that receives the webhook verifies the signature, persists the event and answers. The real work happens on a separate queue, with increasing back-off and a dead letter queue where whatever cannot be processed ends up.
Processing inside the request means a slow third party causes timeouts, and many senders disable a webhook that fails repeatedly. You lose the integration over a temporary slowdown.
Signature, not trust
Every inbound request verifies its signature with a constant-time comparison and rejects old timestamps. Every outbound call authenticates with rotatable, minimum-scope credentials.
A public endpoint with no verification is a write form open to the internet, pointed at your management system.
Ordering and rate limits
Events do not necessarily arrive in order, and the other end has a per-minute call limit. Both are solved in the design: a version number per entity so stale updates get discarded, and throttling with back-off that respects the retry-after header.
Ignoring order means an old state overwrites a newer one. Ignoring the limit produces throttling that shows up precisely during volume peaks.
What you get
- ▪ Inbound endpoints with signature verification and an event log
- ▪ Queue with exponential retry and a reviewable dead letter queue
- ▪ Idempotency key per operation, persisted next to its effect
- ▪ Per-message status dashboard: received, processed, failed, retrying
- ▪ Alerts on the age of pending items and on dead letter queue growth
How we build it
Idempotent by default
Every operation can be repeated without duplicating anything. That is what makes a retry safe, and without it no integration survives its first dropped connection.
Observable state
Every message has a state you can query: pending, sent, confirmed, failed. An integration you only notice when it breaks had already been breaking for a while.
One owner per field
For each field there is one system that decides and the others follow. Bidirectional sync without that rule ends in loops and in data that changes on its own.
AI where it judges, not where it calculates
Classifying, extracting and drafting are model work. Adding up, validating and routing are code work. Swapping them round is expensive and impossible to audit.
How we work
The people who run the diagnosis are the people who build it. No hand-offs. The full method and the rest of the capabilities are on the systems integration page.
- 01 Diagnosis · 3–5 days
We map systems, data flows and the dependencies that actually exist, including the ones nobody wrote down. Output: a closed scope and the list of what is broken today.
- 02 Integration design · 1 week
Data contracts, direction of sync, retry policy and who owns each field. This is settled before any code gets written, because it is the expensive thing to change later.
- 03 Build and testing · 2–6 weeks
Built against the real edge cases, not the happy path. Tested against the actual systems and rolled out in stages.
- 04 Production and observability · ongoing
Status dashboard, alerts when something has gone too long without confirmation, and maintenance of the integrations when third-party APIs change under you.
Related to this case
What usually comes before or after, with the reason we link it.
Legacy systems
When the other end has no API, this pattern stops applying and a different one takes over.
Open →n8n vs Zapier vs Make
The other half of the decision above: which of the three tools holds up, and where each one runs out of road.
Open →ERP integration
The most common destination for these connectors.
Open →Technology architecture
Where the contracts, sync direction and ownership rules get decided, before anyone writes a connector.
Open →Questions about this case
What is the difference between integrating over an API and over a webhook? +
Who takes the initiative. With an API you ask when you want to: it is predictable and you control the pace, but you find out late and you spend calls asking about things that haven't changed. With a webhook the other system tells you when something happens: immediate and efficient, but it forces you to be available always and to tolerate repeats. Most serious integrations use both: the webhook to find out, the API to confirm the detail.
What happens if the other system goes down? +
Messages pile up in the queue and get retried with increasing back-off until the service returns. What you must never do is let a third party's outage stop your own operation: your flow carries on and the sync catches up afterwards. That is exactly why the queue exists.
Do you use n8n or build everything custom? +
Both, and the choice gets argued case by case. n8n covers orchestration and frequently changing flows very well, with the advantage that your team can edit them without depending on us. What we pull into code are the pieces with hard requirements: high volume, transactions, complex error logic, or anything that has to be auditable. Mixing the two worlds usually costs less than picking one on principle.
Who maintains the integration when a third-party API changes? +
It is part of the maintenance agreement, and it is worth being explicit about that. Third-party APIs change without telling anyone in particular: they retire versions, tighten limits, rename fields. An integration with nobody watching for those changes works right up until it doesn't, and it is normally a customer complaint that tells you.
Start with the diagnosis
Three to five days to know what gets connected first, with scope and price closed before a line of code is written.
Talk to a specialist ↗Other cases