Cost & planning

Why a quick integration is never quick

EdgeBrain Studios12 min read

The documented endpoint is the cheapest part of a third-party API integration. You’re not buying a call, you’re buying a surface: authentication that expires on its own schedule, pagination that changes shape past page one, rate limits you meet in production, partial failures with nothing to roll back, and a deprecation notice that lands in month nine. Our own working estimate: a shallow read-only integration against a well-run API is three to eight engineering days. One that writes money, legal state, or user records in both directions is four to twelve weeks. The call itself is an afternoon in both cases.

Everything between those two numbers is surface. Below are the fourteen things that live on it, and then the part almost nobody quotes: an integration doesn’t finish. It becomes a standing line item on somebody’s budget.

What moves a third-party API integration cost

Estimates in engineering days, because a day is portable and a dollar figure isn’t. These are our own numbers for a two-person team working against an API with real documentation.

Integration classShapeOur estimate
Shallow readOne resource, low volume, no history3 to 8 days
Read plus backfillSeveral resources, years of history to import2 to 5 weeks
Bidirectional syncBoth sides can edit, non-financial records4 to 8 weeks
Writes money or legal statePayments, payroll, shipping, compliance filings8 to 16 weeks
Real timeTelephony, streaming, presence, live pricing6 to 14 weeks

Four provider properties move you between those rows faster than your own requirements do. Whether idempotency keys exist. Whether webhooks exist or you have to poll. Whether the sandbox holds realistic data. Whether error responses distinguish “retry this” from “never retry this.” An API missing all four turns a two-week job into a two-month one, and no amount of skill on your side changes that.

Against our published bands, a single integration delivered as a production workflow starts at $12,000, and most projects land between $18,000 and $45,000. When the integration is the whole project rather than a line inside a bigger build, that’s the range it sits in. Those bands are estimates in US dollars, not quotations; the quote that follows scoping is fixed in writing before kickoff.

The fourteen things between a documented endpoint and a working one

Eight of these carry most of the cost, so they get their own section. The last six are smaller, and they’re in a table underneath.

1. The token refresh that silently expires

OAuth 2 access tokens commonly live an hour. Fine. The expensive part is the refresh token, which on a growing number of providers rotates: each refresh returns a new one and invalidates the old. Lose the response to a single refresh call and the grant is orphaned, with no error anywhere in your logs.

Refreshing has to be single-flight and locked across processes, because two workers refreshing the same rotating token at the same moment kill each other’s grant. Then there’s absolute expiry, inactivity expiry, user revocation, an admin pulling a scope, and a password reset that invalidates every session. Each one needs a detection path and a re-consent flow, which is product surface, not a backend patch.

2. Pagination that changes shape past page one

Docs show page one. Page one is always the well-behaved one. Offset pagination over a live collection skips and duplicates records as rows shift underneath the scan. Cursor pagination fixes that and introduces cursors that expire mid-scan, so a long import has to resume from a checkpoint rather than restart from zero.

Add undocumented maximum page sizes, an approximate total count, and nested collections that paginate independently. The design consequence is the whole cost: every read path has to be resumable, and every write it triggers has to be idempotent.

3. Rate limits discovered in production

The published number is rarely the enforced one. Real limits stack: per-endpoint, per-organisation, per-credential, plus a concurrency cap nobody documented and a burst bucket that refills more slowly than the steady-state figure implies. Some providers return 429 with no Retry-After header, which means you’re guessing.

What that buys you is a token bucket per credential, exponential backoff with jitter, and a queue with priority classes so a backfill can’t starve the interactive request a user is waiting on. Two days of work you do once and reuse, if you knew to scope it.

4. Sandbox data that never contains the edge case

A sandbox is a happy-path generator. It won’t hold the customer with 12,000 line items, the charge that was refunded and then disputed, the record with a null in a field the schema marks required, or the account whose name carries an emoji and a right-to-left mark.

Our position: budget a production shadow run before you call an integration done. Read real data with production credentials, write nothing, and diff what your code would have done against what the system actually holds. It costs two to four days and it is the highest-yield item on this list.

5. Optional fields that turn out to be load-bearing

A field is marked optional because it’s optional to the provider’s schema, not to your business. Currency gets omitted when it matches the account default. A tax identifier appears only in certain jurisdictions. An array is absent rather than empty. A nested object is present and every leaf inside it is null.

Every optional field your logic reads is a branch, and branches are where estimates go to die. Enumerate them during the spike and decide the default for each in writing. Finding the eleventh one in production costs more than the first ten combined, because by then you’re repairing data as well as code.

6. Partial failure with nothing to roll back

Your request times out after the provider committed. There is no transaction spanning your database and theirs, and there never will be. Retrying blindly double-charges, double-ships, or double-hires.

The pattern that works is boring. Generate and persist an idempotency key before the call, store the request and the response, and run a reconciler that asks the provider what actually happened rather than inferring it. If the provider offers no idempotency key you build a dedupe table on your own request hash and accept a window where you’re guessing. The payments version of this is written up in detail in how to run Stripe webhooks in production, and the shape generalises to any provider.

7. Webhook replay, ordering, and the ones that never arrive

Webhook delivery is at-least-once, out of order, and retried for hours or days. You’ll get the same event twice, get an update before the create it depends on, and occasionally not get one at all because your endpoint was down for ninety seconds during a deploy.

Two rules cover most of it. Deduplicate on the provider’s event id, persisted behind a unique constraint. And never apply the payload as a diff: treat the webhook as a hint that something changed, then fetch current state by id. Add signature verification against a secret that rotates, a replay window, and a scheduled reconciliation pass for events that vanished. That’s a week on its own for anything important.

8. The backfill nobody scoped

Live sync is the easy half. Importing four years of history is a separate program that happens to share a client library. It needs its own throttle, its own checkpointing, its own resumability, and an upsert path that’s safe to re-run from any point.

It also collides with live traffic on the same records, so you need a rule for which write wins. Design a backfill to be interrupted, because it will be.

The other six

ItemWhy it costs
Identity reconciliationTheir ids to yours, plus merges, deletes and re-creates on their side that your foreign keys never hear about
Units, currency, timeMinor units versus decimals, rounding rules, and recurring dates that shift across a daylight-saving boundary
Credentials per environmentSeparate keys for sandbox and production, rotation without downtime, and secrets that never enter the repository
ObservabilityCorrelation ids, per-endpoint failure rates and stored payloads, because you can’t debug a black box on someone else’s server from a stack trace
API versioningPinning a version, reading the changelog, and owning an upgrade path you will walk more than once
The provider support loopBugs only they can fix, answered on their response time, which is not in your sprint and not in your control

Then the deprecation email arrives in month nine

Sunset windows run from roughly ninety days to a year, depending on the provider’s culture and whether a regulator or a security finding is forcing the change. A field gets removed, an auth flow gets replaced, a version reaches end of life.

That is not maintenance. It’s a small project scheduled by somebody else, with a hard deadline you never agreed to. Teams who budgeted a percentage for upkeep discover their percentage was a smooth line and the reality is lumpy.

The integration doesn’t finish, it becomes a line item

Nearly every agency article on this topic quotes 15 to 25 percent of build cost per year for maintenance, and none of them cites anything. We think the percentage framing is wrong regardless of the number, because maintenance load doesn’t scale with what you spent building. It scales with how often the provider changes.

Count interruptions instead. Our own expectation, per active provider per year: one to two breaking or deprecating changes, a handful of incidents on their side you have to absorb gracefully, at least one credential or consent expiry, and a continuous trickle of “why didn’t this record sync” tickets that are usually data problems rather than code problems.

Then multiply by providers. Ten integrations is not ten times the cost of one. It’s ten independent release calendars you don’t control, landing on a team whose sprint has a fixed number of hours in it. That’s the number nobody puts in the quote, and it is the one that decides whether you should build at all.

Price it as reserved capacity rather than a percentage. Our published retainers start at $2,500 a month against a capped block of hours, and what a given system needs inside that depends on provider count, how customer-facing the failure is, and whether an outage costs money the same day.

When you should buy the connector layer instead of building it

This is the section that costs us work, and it’s the honest one. Unified APIs and iPaaS platforms are a genuinely correct purchase in one specific shape: many providers, one shallow object, no custom write semantics. Reading contacts from fifteen CRMs, employees from eight HR systems, or ledger entries from six accounting tools is exactly that shape. Building fifteen connectors so you can own them is a bad trade, and anyone quoting you for it should say so out loud.

The lighter version of the same argument: if your integration is a scheduled data movement with modest branching, a workflow tool gets you there in days rather than weeks and it stays legible to people who aren’t engineers. We build those deliberately as n8n workflow automation, because handing you a workflow you can read beats handing you a service only we can change.

Where the vendor conclusion breaks down is the deep single provider. Payments, telephony, carrier logistics, clinical records. A normalised model has to erase whatever its providers don’t share, and the field it erases is often the one your product is built on. You also inherit a second vendor, a second failure domain, a second latency hop and a second deprecation calendar, stacked on top of the provider’s own. The surface didn’t disappear. It moved, and it grew a layer.

Our own bias runs the other way and you should price it in: we build integrations, so our instinct is to build. That instinct is wrong for a team whose integration list is long, shallow and mostly identical.

How we scope one so the estimate survives contact

We don’t fix-price an unfamiliar API. Before a number exists there is a paid spike, typically three to five days, and it has deliverables rather than a feeling.

  • Authenticate against production credentials and force one full refresh cycle.
  • Page through the largest real collection, end to end, and time it.
  • Trigger a 429 deliberately and record exactly what comes back.
  • Perform one successful write and one deliberately failed write.
  • List every optional field our data actually reads, with a decided default for each.
  • Read eighteen months of changelog and note the breaking-change cadence.

That spike either produces a fixed price we’ll stand behind or tells us to quote time and materials, which is a trade-off we have argued through in fixed price versus time and materials. If a client won’t fund the spike we quote wide or decline, and we say which one we’re doing. A cheap precise number for work nobody has looked at is the most expensive thing in this article.

What we won’t agree to build

A fixed-price integration against an API with no sandbox, no changelog and no status page. A buffer large enough to cover that stops being a price and starts being a guess.

A bidirectional sync where both sides can edit the same field and nobody has decided who wins. That isn’t an engineering question and we can’t answer it for you. Decide it, write it down, and the build gets ordinary.

A customer-facing real-time integration on a provider that publishes no SLA and no rate-limit numbers. When the integration is the product rather than a side quest, the provider’s reliability becomes yours. Our desktop voice agent built for a client sits on live telephony and a realtime model at the same time, which is exactly the case where two providers’ failure modes land in a user’s ear instead of a log file.

The compressed version

Price the surface, not the endpoint. Ask whether the provider offers idempotency keys, webhooks, a realistic sandbox, and error codes that separate retryable from fatal. Those four answers move the estimate more than your requirements do. Fund a spike before you accept a fixed price, and treat the backfill as its own project.

Then budget the standing cost, because the alternative is discovering it during somebody else’s sunset window. If your provider list is long and shallow, buy the connector layer. If it’s one deep provider your product depends on, own the code. Tell us what you’re connectingand we’ll tell you which of the two we’d actually recommend, including when that’s the one we don’t get paid for.

Got a version of this problem?

Send a paragraph describing what you’re trying to build and what’s currently in the way. We reply inside two working days with a scope, a price and a start date. If we’re not the right people for it, we say that instead.