Connecting to a well-documented API is a day's work. Keeping that connection trustworthy for two years, across their outages and your deploys, is the actual project. These are the patterns that make the difference.
Never trust a webhook as the only signal
Webhooks are fast and convenient, and they will be missed. Endpoints go down, deploys drop requests, providers retry with delays, and events arrive out of order.
The pattern that holds is webhooks for speed plus a periodic reconciliation job for correctness. The webhook updates state immediately; the reconciliation job asks the provider what actually happened over the last window and fixes any disagreement. Without the second half, your database and Stripe slowly diverge and nobody notices until a customer asks.
Make every write idempotent
Retries are not an edge case, they are normal operation, yours and theirs. Any operation that creates something must be safe to run twice.
Stripe provides idempotency keys for this and they should always be used. For providers that do not, generate a stable key from your own data and record what you have already sent, so a retry becomes a lookup instead of a duplicate invoice.
Decide which system owns each field
This is the failure we see most often, and it is not technical. A contact exists in your product and in HubSpot; a customer exists in your product and in QuickBooks. When both sides can edit the same field, they will, and the last writer wins arbitrarily.
Write down field ownership before building the sync. Some fields your product owns and pushes; some the CRM owns and you only read; a few genuinely need a merge rule. Any field without an owner will eventually produce a support ticket nobody can explain.
- One owner per field, recorded somewhere findable
- One-way sync wherever you can get away with it
- Explicit merge rules for the fields that truly need them
- A log of what changed, from which side, and when
Treat the provider as unreliable
Third-party APIs are slow sometimes, rate-limited sometimes, and down occasionally. If a provider's bad afternoon takes down your checkout or blocks your order pipeline, the integration is not finished.
Queue outbound work rather than calling providers inline, retry with backoff, respect rate limits, and give failed items somewhere visible to land. The goal is that a provider outage delays work rather than losing it.
Make it observable to non-engineers
The people who notice integration problems first are usually in finance or operations, not engineering. Giving them a screen that shows what synced, what failed, and what is waiting turns a support escalation into a self-service check.
It also shortens debugging considerably, because the first question (did the event arrive at all?) gets answered without opening a log.