Retries & Idempotency
Retries & Idempotency
Network failures are ambiguous.
A timeout, dropped connection, or process restart can prevent your application from receiving a response even though Penny may already have processed the request.
For read-only requests such as GET, retrying is normally safe.
For operations that create resources or move money, use the operation’s documented retry mechanism rather than blindly submitting the request again.
An Idempotency-Key tells Penny whether a request is a retry. Send the same key and Penny returns the original result instead of repeating the operation. Send a different key and Penny treats the request as a new operation.
Idempotency keys
These endpoints accept an Idempotency-Key header:
The header is optional, but we strongly recommend sending it on every money-movement request. Without it, Penny cannot recognize a retry, and a retried request is processed as a new operation.
Generate one unique key for each intended operation, persist it before sending the first request, and reuse that same key only when retrying that operation.
Even if Transfer A and Transfer B have identical request bodies, they represent different intentions and must use different keys.
A UUID or ULID is a good choice. Keys can be up to 255 characters.
A successful transfer returns 201 Created with both sides of the movement:
The transaction objects are abridged here. See Transactions for the full shape.
Retrying with the same key
When retrying the same intended operation, reuse the original key and send the same request body.
Never generate a new idempotency key because the first request timed out. A new key represents a new intended operation and can create a second transfer.
Idempotency key scope and retention
Penny scopes each key to your business and to the operation it was sent with. The same key sent to a different endpoint is a separate key.
Penny keeps each key for 7 days. After that, a request with the same key is processed as a new operation.
Store the idempotency key alongside your own record of the intended operation so the same key can be reused during recovery.
Client Reference
Some Penny resources and transactions support a client_reference.
Use it to associate Penny activity with an identifier from your own system:
You can then query transactions using that reference:
client_reference is useful for:
- reconciliation;
- tracing an operation back to your system;
- investigating an ambiguous outcome.
It is not an idempotency mechanism.
Penny does not require client_reference to be unique and does not deduplicate requests based on it.
For endpoints that support both values:
- use
Idempotency-Keyto make retries safe; - use
client_referencefor reconciliation and lookup.
Ambiguous outcomes
A timeout or 5xx response does not necessarily mean the operation failed.
Treat it as an unknown outcome until you determine whether Penny processed the request.
Do not assume:
no response = no side effect
Creation endpoints without idempotency
Endpoints that do not accept an Idempotency-Key, such as POST /cards/virtual, need more care after an uncertain result: Penny cannot tell an intentional second card from a retried duplicate.
Where the API provides suitable lookup fields:
- retain the identifiers and request context from the original attempt;
- query for the intended resource;
- determine whether the original operation appears to have succeeded;
- create again only when you can establish that doing so will not produce an unintended duplicate.
Do not invent a resource ID you did not receive, and do not assume a list lookup is an atomic duplicate-prevention mechanism.
If your integration requires a stronger exactly-once creation guarantee for an endpoint that does not support idempotency, contact Penny before relying on automated retries.
Retry guidance
Use the following as a starting point, then follow the operation-specific error contract.
See Errors & Rate Limits for general error handling.
Recommended integration pattern
For every operation that supports idempotency:
- create a unique operation ID in your system;
- generate and persist an idempotency key;
- send the request;
- store the resulting Penny resource or transaction ID;
- reuse the original key for retries of that same operation;
- use
client_referencewhere available to support reconciliation.
For example:
This makes the intent of each operation explicit and gives both systems identifiers that can be used during recovery and reconciliation.