Skip to main content
The TapAce SDK retries temporary request failures during a call. Once those attempts are exhausted, your application receives an error and decides what to do next.

Retry behavior

Defaults are three retries after the initial attempt and a 30-second timeout per attempt. Ordinary retry waits use exponential backoff with jitter: roughly 300–400 ms, 600–800 ms and 1200–1600 ms. Exponential backoff is capped at 30 seconds before jitter, including when you configure more retries. There is no single overall call deadline. Set maxRetries: 0 to disable retries.

Automatic and stable keys

The SDK generates a random key once for each POST, PATCH, PUT or DELETE call unless you supply one. It reuses that key and the same serialized request body across internal retries. A separate call generates a different key. For an operation your application might repeat, derive a stable key from a saved operation ID:
Same helper inputs, in the same order and with the same types, produce the same key after a restart. The helper accepts strings, finite numbers and booleans, requires at least one part and rejects blank strings. It hashes the parts rather than placing raw identifiers in the header. Use an operation ID, not just a customer ID: one customer can legitimately receive several passes or points awards. Keep the request details unchanged when retrying. The API’s idempotency guide documents seven-day retention. After that window, reconcile the original operation before issuing another request; a stable key is not permanent duplicate protection. An in-flight conflict may outlast SDK retries. See Retry after a restart.
Sending a key and enforcing idempotency are separate. Stored-response replay applies to POST, PATCH and DELETE API requests. PUT event and signing requests do not currently provide the same replay protection. Read their current state before deciding how to repeat a change.

Error classes

Transport, configuration, API and webhook errors extend TapAceError. Invalid inputs to idempotencyKey() throw TypeError; a request body that cannot be JSON-serialized can also throw TypeError before any HTTP request. API errors extend TapAceAPIError and expose status, type and optional code, issues and requestId. Check the more specific subclass first:
A timeout does not prove the server rejected the operation. Retry a mutation with the original stable key rather than generating a new one.

Keep separate keys for separate changes

For loyalty credits, derive the key from a saved sale or award ID. Retrying a two-stamp award must reuse its original key and { add: 2 } body; a second purchase needs a different key. The same rule applies to points, notifications and deployments.

Retry after a restart

A key is not a job queue. When the process exits, the SDK loses its in-memory request and does not discover unfinished work. To retry across restarts, save the request before sending it, then resend it with the same key and body. How a retry behaves depends on what happened to the original request:
  • TapAce finished it before your process died: within retention, the same key and body replay the saved response.
  • It died partway through: the key stays in flight until ten minutes after it was reserved, then a request with the same key and body can take over. The ten-minute mark does not schedule anything, and default SDK retries finish much sooner, so your own retries must continue past it.
  • It is more than seven days old: the key may be gone, so check your saved pass ID or other records before repeating it. An externalId helps find passes but is not unique.
This recovery behavior does not guarantee that every mutation runs exactly once.