Skip to main content
Skip to content

Writing a client

Retries, backoff, pagination and the four failures worth handling separately.

The API is small enough that a client is a hundred lines. Most of the work is in handling the four failures differently, because retrying the wrong one wastes time and retrying another makes things worse.

StatusRetry?Because
401NoThe key is wrong, absent or expired. Retrying sends the same wrong key.
403NoThe key lacks a scope. Only a new key with different scopes fixes it.
404NoNot this key's workspace. Retrying will not change whose workspace it is.
429Yes, after Retry-AfterA limit, not a fault. The header tells you how long.
503Yes, with backoffLoad protection or a transient read failure. Not caused by your traffic.

Backoff

  • Honour Retry-After when present; it is computed from the window rather than guessed.
  • Otherwise exponential with jitter. A fixed interval across several clients reconverges into the spike that caused the limit.
  • Cap the total attempts. A client that retries forever turns a five-minute provider blip into an outage of its own making.
  • Never retry inside a request a person is waiting on. Queue it and answer.

Pagination

Read hasMore rather than comparing the array length against your limit, and pass nextCursor back verbatim. Do not construct a cursor: it is opaque, its contents are an implementation detail, and one you build by hand can stop working without a version bump because it was never part of the contract.

Keys in a client

  • Read the key from the environment. Never from a file in the repository, and never as a default argument.
  • Log the keyId from /auth, never the key.
  • Set a rotation reminder shorter than the expiry. Nothing warns you.
  • One key per integration. A shared key means a rotation takes down everything at once and you cannot tell which caller hit a limit.