Home/Services/Integration & API Development
Service · Build software

APIs and integrations that fail loudly, safely, rarely.

Contract-first APIs, event-driven integration and the unglamorous discipline — idempotency, retries, dead-letter queues — that keeps enterprises consistent.

Integration & API DevelopmentWhat we do
01Contract-first API design
02Event-driven backbones
03Legacy & SaaS connectivity
04Failure engineering
How it runs
  1. System mapping
  2. Contracts
  3. Build & shadow
  4. Cutover & observe
Why it exists

Built for the day the other side fails.

Every enterprise is an integration problem wearing a business model. ERP, CRM, payment rails, partner feeds — the value is in the joins. We design APIs as contracts and integrations as event flows with explicit failure behaviour, because that is the part that decides whether the estate holds together on a bad Tuesday.

The pattern we meet most often is not a missing integration. It is many of them, written by several teams over many years, each with its own retry logic, its own idea of what a customer identifier is, and no shared view of whether anything is currently flowing. Nightly files paper over the gaps; a reconciliation spreadsheet papers over the files. Our job is to replace that with a small number of governed contracts, an event backbone where facts belong on a log, and enough observability that a broken flow is a prompt alert rather than a month-end surprise.

The test of an integration is not the happy path — it’s what happens when the other side is down, slow, or sends the same message twice.

What we do

Four disciplines, applied in that order.

Contracts first, because they are cheap to change on a whiteboard and expensive to change in many consuming systems. Failure behaviour last to be forgotten, because it is what you actually live with.

01

Contract-first API design

OpenAPI specs before code. Versioning, pagination and error semantics agreed while they’re cheap to change. We write the contract with the teams that will consume it, generate server stubs and client SDKs from it, and enforce compatibility rules in CI so a breaking change fails the build rather than a partner’s integration.

02

Event-driven backbones

Kafka / queue-based integration with the outbox pattern — no dual-write races, no silent loss. The event is written in the same database transaction as the business change and relayed by a connector or Debezium, so a producer can never commit a fact and lose its notification. Consumers are idempotent, keyed on a business identifier, and commit offsets only after the effect is durable.

03

Legacy & SaaS connectivity

SOAP fronting, file-drop ingestion, webhook normalisation — meeting systems where they actually are. A mainframe that nobody may modify becomes an event source through change data capture; an FTP drop becomes a validated, replayable feed. Behind the wrapper we modernise at our own pace, and consumers never see the difference.

04

Failure engineering

Idempotency keys, retry budgets, dead-letter queues and replay tooling — designed in, not bolted on after the first incident. Every flow we hand over has a written answer to four questions: what happens when the target is down, when it is slow, when it returns an error, and when the same message arrives twice. That answer is tested, not assumed.

In practice

How the work runs, day to day.

01

The contract is the deliverable, not the code.

An API that ships before its consumers have read the specification will be redesigned in production, in front of an audience. We invert that. The OpenAPI or AsyncAPI document is written first and reviewed with every consuming team — resource shapes, pagination, idempotency headers, error codes, rate limits and the deprecation policy. Only when the contract survives that review does implementation start, generated from the same document that the client SDKs and the mock server come from. Consumers can build against the mock once the contract is signed, which takes sequencing out of the plan.

  • OpenAPI 3.1 and AsyncAPI documents under version control, reviewed as pull requests like any other change
  • Additive-change policy with compatibility checks in CI — a breaking field removal fails the pipeline
  • Deprecation windows backed by usage telemetry, so you can see who still calls v1 before switching it off
02

Facts on a log, not calls into the dark.

A synchronous call between two systems couples their uptime, their throughput and their release calendars. Where the interaction is really a fact that several systems need to know about — an order placed, a shipment tendered, a payment cleared — we publish it once to a durable, ordered log and let each consumer read at its own pace. A slow system stops being everyone’s problem, an outage becomes a backlog rather than a loss, and a bug that corrupted a downstream table is fixed by replaying a time range instead of re-keying data. The producer side uses the outbox pattern, so the fact and its event share one commit.

  • Topic ownership, keys, schemas and retention recorded in an event catalogue that lives in the repository
  • Schemas in a registry with compatibility rules enforced in CI — Avro, Protobuf or JSON Schema
  • Change data capture from Oracle, SQL Server, MySQL or PostgreSQL where the source cannot be changed
03

Failure behaviour, decided in advance.

Integrations do not usually break with an exception. They break with a timeout on one side and a committed write on the other, or with a partner replaying yesterday’s file, or with a retry storm that turns a slow dependency into a dead one. We write the failure policy per flow before the code: what is retried and how many times, what backs off, what is held, what goes to a dead-letter queue, who is paged and what the replay procedure is. The policy is a table you can read in a review, and it is tested with fault injection before cutover rather than discovered at 03:00.

  • Idempotency keyed on a business identifier so at-least-once delivery produces exactly-once outcomes
  • Retry budgets with exponential back-off and circuit breakers, so a slow dependency cannot be turned into an outage
  • Dead-letter queues with a rehearsed replay procedure and alerting on dead-letter volume, not just on errors
Target returns 5xx or times outRetry 5× with back-off, then dead-letter
Target returns 4xx (bad payload)Dead-letter immediately, page owner
Same idempotency key seen againAcknowledge, do not reprocess
Error rate > 5 % for 2 minutesOpen circuit, hold on the log, alert
Dead-letter queue non-empty at 15 minAlert integration owner with replay link
04

Shadow first, cut over second.

The riskiest hour in an integration programme is the one where a new flow starts writing to a system of record. We remove it. New integrations run in shadow mode against real production traffic — consuming the same inputs, producing the same outputs, writing nowhere — while a comparator reports every difference between the new result and the current one. Differences are worked down until the remaining ones are explainable and agreed. Only then does the flow start writing, usually for one segment first, with the old path still warm and a rehearsed rollback.

  • A comparator that reports differences by type and volume, not a sample someone eyeballed
  • Cutover by segment, partner or region, each step reversible
  • The legacy path kept running until the difference report has been clean for an agreed period
By seat

Three people care about an integration, for three reasons.

Platform & architecture

One estate, governed, with a picture that is true.

You get an inventory that reflects reality: every flow, its owner, its contract, its consistency requirement and its failure policy. New joins go through the same review, so the estate does not re-fragment after we leave. Where the right answer is fewer integrations rather than better ones, we say so — a point-to-point flow that exists because two teams could not agree on ownership is a governance problem, not an engineering one.

  • System and flow inventory with data owners and consistency requirements
  • Standards for REST, GraphQL and events — and the rule for choosing between them
  • Gateway policy: authentication, rate limits, keys, quotas and a docs portal
Operations

You find out from a dashboard, not from a customer.

Every flow we hand over ships with its own view: throughput, lag, error rate, dead-letter depth and the age of the oldest unprocessed message. Alert policies are exported as code alongside the flow, so a new integration cannot reach production without them. The runbook for each failure mode is written by the engineers who built the flow and rehearsed with your team in a game day before go-live.

  • Per-flow dashboards and alert policies, versioned with the code
  • Runbooks per failure mode, rehearsed rather than filed
  • Replay and reconciliation tooling your on-call can run without us
Partner & product

An API a partner can onboard onto without a call.

External APIs are a product with a support cost. We build the gateway layer with the developer experience attached: self-service keys, sandbox credentials, generated reference documentation, code samples and a changelog that says what changed and when the old behaviour stops. Rate limits and quotas are per consumer, so one enthusiastic partner cannot degrade the rest, and usage telemetry tells you which endpoints are actually earning their maintenance.

  • Self-service onboarding: keys, sandbox, generated docs and samples
  • Per-consumer rate limits, quotas and usage telemetry
  • Versioning and deprecation communicated on a schedule, backed by call data
Scope

What is in every engagement, and what is shaped per estate.

CapabilityIn every engagementShaped per estate
Flow inventory with owners and consistency requirements
Contract-first design with CI compatibility checks—
Outbox pattern on producers that must not lose events—
Idempotent consumers with dead-letter and replay—
Shadow running with a difference comparator
Change data capture from a legacy system of record—
API gateway, keys, rate limits and docs portal—
Partner onboarding and sandbox environment—
Per-flow dashboards, alert policies and runbooks
Game day with your on-call team before handover—
Ongoing operation of the flows to agreed SLOs—
How it runs

Four phases, and nothing writes until it has been shadowed.

01

System mapping

Inventory of systems, data owners and flows — and the consistency requirements each join really has. We work out which joins need to be strongly consistent, which can be eventually consistent by seconds, and which have been nightly for years without anyone minding. That answer determines the architecture, and it is usually cheaper than the one people assume.

02

Contracts

OpenAPI / event schemas reviewed with every consuming team before implementation starts. Each contract carries its error semantics, idempotency rules, retention and ownership. Mock servers and generated SDKs go out with the signed contract, so consuming teams build in parallel with us instead of waiting for us.

03

Build & shadow

Integrations run in shadow mode against production traffic, outputs compared before anything cuts over. Fault injection covers the failure policy — target down, target slow, duplicate delivery, malformed payload — and the comparator report is worked to zero unexplained differences before a date is agreed.

04

Cutover & observe

Staged cutover with per-flow dashboards, alerting on lag and failure rates, and documented replay procedures. We move one segment at a time with the old path warm, then hand over the runbooks in a game day with your on-call team. Nothing is declared done because it deployed; it is done when your team has run the recovery once.

What you get

What you have at the end.

  • OpenAPI / AsyncAPI contracts under version control
  • Deployed integration flows with monitoring dashboards
  • Idempotency, retry and dead-letter policies — documented and tested
  • Replay and reconciliation tooling
  • Runbooks for every failure mode we designed for
  • An event and endpoint catalogue with owners, keys, schemas and retention
  • Infrastructure and alert policies as code, in the same repositories as the flows
Usually built with
Node.jsJavaKafkaRabbitMQPostgreSQLDebeziumOpenAPIGraphQLKongOpenTelemetry
Fit

When this is the right call.

Right fit

Choose this when more than a handful of systems have to agree about the same facts, when a join carries money or a regulatory obligation, or when the current estate is a set of point-to-point scripts whose owners have left. It is also the right call before a modernisation or legacy re-engineering programme: a governed integration layer is what lets you replace a system of record without renegotiating with every consumer. And it is the right call when partner-facing APIs are becoming a product, with the onboarding, versioning and support that implies.

Look elsewhere

It is not the right call for a single connection between two systems that a product team can own end to end — that is a sprint, not a programme, and we will say so. It is not the right call when nobody will own the contracts, the schemas and the consumer lag after we leave; an unowned integration layer becomes a very durable place to lose data. And if the real problem is that two departments disagree about who owns the customer record, no amount of engineering will settle it — that conversation has to happen first.

FAQ

Frequently asked questions

Different jobs: REST for resources, GraphQL for aggregation-heavy UIs, events for decoupled system-to-system flows. Most estates need a deliberate mix, and the failure mode is picking one and forcing everything through it. We write the rule for choosing into your standards so the next team does not have to relitigate it.
Usually — we’ve fronted SOAP, files-on-FTP and databases-as-interfaces. The pattern is to wrap, normalise, then modernise behind the wrapper. Where the source cannot be touched at all, change data capture reads its write-ahead log and turns it into an event stream with no change to the system itself.
Versioned contracts, additive-change policy, deprecation windows with usage telemetry — you can see who still calls v1 before turning it off. Compatibility is checked in CI against the published schema, so a breaking change is caught in a pull request rather than in a partner’s incident report.
We build the gateway layer too: auth, rate limiting, keys, docs portal — an API partners can onboard onto without a call. Sandbox credentials, generated reference docs and a published changelog come with it, because the support cost of an external API is decided by how self-service the first day is.
Yes — audit first, stabilise the riskiest flows, then re-platform incrementally with shadow traffic. The early work usually buys the most: monitoring on flows that had none, idempotency on the ones that double-post, and a written inventory so the estate stops being folklore.
Your choice. With runbooks and a rehearsed game day, your team can run them. Where you would rather we kept the pager, we operate the flows to agreed SLOs — see engagement models for how that is structured.

Tell us what you’re building.

Describe what exists today and what you need. An engineer reads it and replies in writing with how we would approach it.

✓ No pitch deck✓ Reply from an AI-native engineer✓ Written follow-up