APIs & Integrations
Common Mistakes When Integrating Third-Party APIs
The integration bugs that survive demos: auth and JWT expiry, pagination that stops at page one, timezone-blind timestamps, and retries that double-apply money and stock.
Palmate Solutions Editorial · Published 11 June 2026 · Updated 20 July 2026 · 5 min read
Third-party APIs rarely fail in the Postman happy path. They fail when a token expires at 2am, when page 2 is empty because you used the wrong cursor, when “order date” was local time labelled as UTC, and when a timeout retry captured a payment twice. Palmate Solutions’ API integration work is largely the prevention of those classes of mistake.
This article is a field guide. Pair it with the API integration checklist for businesses before you write glue, and with how API integration can automate operations if you still need the case for doing this at all.
When a payload looks “fine” and is not, paste it into the JSON formatter. Invalid JSON, trailing commas, and comments are still common in copied samples.
Mistake 1: Treating auth as a one-time login
What it looks like: A key in a .env that worked in week one. OAuth done in a browser once. No alert when refresh fails. Cron continues to post nothing, or worse, posts with a stale token that some vendors treat as anonymous and others treat as a 401 you ignore.
Why it happens: Sandboxes issue long-lived keys. Production uses rotating JWTs or short-lived access tokens. The demo never ran for 24 hours.
What to do:
- Document the grant type. Server-to-server flows need client credentials (or the vendor’s equivalent), not a human click.
- Store refresh tokens like cash. Alert on refresh failure. Build a path to re-auth without redeploying.
- Inspect JWT claims during design with the JWT decoder:
exp,aud,iss, scopes. Confirm the audience is this API, not a sibling product. Do not paste live production tokens into untrusted tools; our decoder runs in the browser. - Clock skew: if your VPS is five minutes slow, “valid token” becomes “not yet valid” or “already expired.” NTP is an integration dependency.
A related failure: putting the secret in the frontend because the mobile app “needed” it. That is not an API integration. That is a leaked key. Mobile apps get their own backend or a tightly scoped token exchange.
Mistake 2: Pagination theatre
What it looks like: Sync job “succeeds.” Downstream has 100 customers. The vendor has 8,400. Page size was 100. You fetched page 1. Or you incremented page until a 200 with an empty list, but the vendor wanted a cursor from the previous payload. Or offset pagination skipped rows that were inserted while you walked the list.
Why it happens: Docs show one request. QA uses a sandbox with 12 records.
What to do:
- Implement the vendor’s actual scheme (cursor,
starting_after,Linkheaders,nextPageToken). - Test a crawl against a dataset larger than one page. If you cannot, you do not know the integration works.
- Prefer
updated_sinceplus a high-watermark stored per job. Full snapshots are for recovery, not every night. - Honour rate limits while paging. A polite complete crawl is better than a banned key.
Empty page ≠ done unless the contract says so. Some APIs return the last page as a repeat; some return 204; some wrap errors in 200. Read the body. Format it. Do not trust the status line alone.
Mistake 3: Timezones and timestamps as strings you sort
What it looks like: “Missing yesterday’s orders.” They were placed in IST and stored as 2026-06-10 with no offset, then filtered as UTC midnight. Or webhook created_at is Unix seconds and your code parsed milliseconds. Or you compared 01/06/2026 as a string and US vs IN day-month flipped a refund.
Why it happens: JSON has no date type. Vendors mix Z, +05:30, naive local, and integer epochs. Dashboards display in the viewer’s zone and hide the crime.
What to do:
- Store instants in UTC. Convert at the edge for display.
- Record the vendor’s raw string and your parsed instant in logs until the mapping is trusted.
- Use the timestamp converter when you are staring at
1718112345versus1718112345000and a human-readable IST/UTC pair. Confirm epoch unit before you write production filters. - Define “business date” separately from “event time” if finance needs an IST calendar day for GST reporting. Those are two fields.
Festival sales will punish this. So will anyone comparing marketplace dashboards to your warehouse clock.
Mistake 4: Retries without idempotency
What it looks like: Client timeout. You retry. Vendor had already applied the first request. Two shipments, two stock decrements, two payment captures. Or webhooks retry for a day and your handler is not idempotent.
Why it happens: HTTP timeouts do not mean “did not happen.” They mean “you do not know.”
What to do:
- Send an idempotency key (vendor-supported or your own stored key) on any POST that creates money, stock, or customer-visible side effects.
- Make webhook handlers check event IDs before applying.
- Retry with backoff on 429 and 5xx. Do not blindly retry 400s that mean “your mapping is wrong.”
- Cap retries. Dead-letter and page a human. Infinite retry of a poison payload is a self-inflicted outage.
At-least-once delivery is the usual webhook contract. Exactly-once is something you build with keys and a ledger, not something you assume.
Mistake 5: Dual authority and sync loops
Two systems both “own” on-hand quantity. A website update pushes to the marketplace; the marketplace echo updates the website; a rounding or pack-size mismatch oscillates. Our sample inventory synchronisation architecture exists because this is normal, not exotic.
Pick an authority. Everyone else receives reserved/available figures. Orders decrement reservations immediately; receipts increment only after confirmation.
Mistake 6: Silent jobs and undocumented mappings
No lag metric. No dead letters. Mappings in one contractor’s head. When it breaks, someone “runs the spreadsheet again.”
If you cannot replay, you do not have an integration. You have a ritual.
A short defensive table
| Area | Demo that lies | Production test |
|---|---|---|
| Auth | Token works today | Refresh + expiry + JWT decoder on claims |
| Lists | First page | Full crawl + incremental cursor |
| Time | One order “looks right” | Epoch vs ISO, IST vs UTC via timestamp converter |
| Writes | Single POST | Retry storm with idempotency keys |
| Webhooks | ngrok once | Signature + replay + out-of-order |
What Palmate will insist on
We will not ship a handler that trusts unsigned webhooks, ignores exp, or pages with hope. We will put mappings in one place, queues behind HTTP, and alerts on lag. That is the job described on our API integration service — contracts, retries, idempotency, and vendor downtime.
Use the checklist so the mistakes in this article are ticked off before they become a support queue. Use the browser tools when you are in the payload: JSON, JWT claims, timestamps. Then automate the flow you can pause and replay.
The unglamorous bugs are the integration. Everything else is a screenshot of 200 OK.
