API development rarely fails in the code. It fails when nobody decided who owns the data, what happens when the receiver is down, and how to change something without breaking a system you do not control. These are the decisions that determine whether the integration still works in three years.
The essentials
- Settle data ownership first. Without it, every error becomes an argument about whose fault it is.
- Design around what the consumer needs, not around how your database happens to look.
- Version from the first release. Adding versioning afterwards costs far more.
- Assume everything goes down. Timeouts, retries and a queue are basic equipment, not luxuries.
- Log enough to reconstruct what happened without phoning the developer.
- Documentation generated from the code is the only kind that stays true.
The decisions that come before code
Four questions settle most of it. Who owns the record when two systems hold it? Is the update real time or batch, and what does a minute of delay actually cost? What happens when the receiver rejects something, does the whole transfer fail or is the record set aside? And who notices?
Answer those four up front and the rest is ordinary craft. Leave them open and you pay for them later, usually while something is broken in production.
REST, GraphQL or messaging
REST suits most system-to-system integration. It is predictable, easy to cache and easy to debug with ordinary tools.
GraphQL earns its place when many different clients need different slices of the same data, typically apps and front ends where the number of calls would otherwise explode.
Messaging and queues are the answer when the sender must not wait for the receiver. Orders, invoices and stock movements usually belong here, because they have to get through even when the other system is down.
Most companies end up with all three. The point is to choose deliberately per integration rather than letting the first decision stand forever.
Versioning and change
The moment another company calls your API, you can no longer change it freely. Put the version in the path from the start, and make it a rule that fields may be added but never removed or renamed within a version.
When something must go, mark it deprecated, log who is still calling it, and contact them. Without that log you are guessing, and guesses become downtime at a customer.
Security, in the order that pays
- Authentication per client. One key shared by everyone means nobody can be cut off without cutting off everyone.
- Rate limiting. Protects against both attacks and a client with a runaway loop.
- Input validation. Never assume the sender sends what was agreed.
- Only the fields needed. The most common data leak is an endpoint returning the whole object.
When the integration meets an older system
This is where most hours disappear. Older systems rarely have an API, often have no documentation, and almost always contain fields used for something other than their name suggests.
Budget for a discovery phase before anyone estimates the build. If the data layer needs cleaning up along the way that falls under database development, and if the old system must keep running meanwhile, under software maintenance.
Running it after launch
An integration is never finished. Certificates expire, receivers change fields, volumes grow. Agree from the start who watches the error log, how quickly someone responds, and how a failed record is replayed.
We build this as part of our API development services, usually alongside application development, and with a dedicated development team where the integrations need maintaining over time.
Frequently asked questions
Two to six weeks when both sides have a documented API. When one side has no documentation, discovery often takes longer than the build itself.
A platform pays off across many similar integrations. For a handful of specific ones it is a subscription on top, and you still write the logic. Count the integrations before deciding.
Choose batch unless somebody can describe what a minute of delay actually costs. Batch is simpler, cheaper to run and far easier to rerun after a failure.
Ask for a test environment, and do not accept “test against production” as an answer. If none exists, build a simulator from the documentation. It costs less than the first production failure.
Before you decide
Settle data ownership, real time versus batch, and what happens on failure before anyone writes code. Version from day one, log enough to answer a customer, and agree who watches the errors a year from now.
Want us to look at your integrations? Get in touch.
