Idempotency
The Sent API v3 supports idempotency for safely retrying requests without accidentally performing the same operation twice. With an idempotency key, the API guarantees at-most-once execution for a mutation: duplicate requests with the same key return the original response instead of executing again.
For retry loops and client implementations that use this contract, see How to retry Sent API requests safely.
How It Works
- The client generates a unique key for each distinct operation
- The client sends it in the
Idempotency-Keyheader - The API caches the successful response for 24 hours
- Duplicate requests with the same key return the cached response
POST /v3/messages
Idempotency-Key: msg_send_abc123
Content-Type: application/json
{
"to": ["+1234567890"],
"template": {
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"parameters": {
"customer_name": "John"
}
}
}Supported Requests
Idempotency applies to every POST, PUT, and PATCH request to a /v3 endpoint that carries the Idempotency-Key header.
| Condition | Behavior |
|---|---|
POST, PUT, or PATCH to /v3/* with Idempotency-Key | Idempotency processing applies |
POST, PUT, or PATCH without Idempotency-Key | Request executes normally; the header is optional |
GET or DELETE request | The Idempotency-Key header is ignored |
Idempotency Key Format
Requirements
- Length: 1-255 characters
- Characters: Alphanumeric, hyphens (
-), and underscores (_) - Pattern:
^[a-zA-Z0-9_-]+$ - Scope: Per customer account
- Expiration: 24 hours
A request with a malformed key is rejected with 400 Bad Request and error code VALIDATION_007 (Invalid Idempotency-Key format).
Valid Examples
req-abc123
send_msg_001
webhook-retry-1
invoice-payment-2024-001
create-contact-john-doeInvalid Examples
req abc 123 # Contains spaces
create@contact # Contains special character @
send.msg.001 # Contains periodsResponse Caching
| Rule | Behavior |
|---|---|
| Cached responses | Only successful (2xx) responses are cached |
| Error responses | Not cached, so a retry with the same key executes the request again |
| Cache lifetime | 24 hours from the original response |
| Response size limit | Responses larger than 5 MB are not cached; duplicates execute again |
| Replayed content | The original status code and body, byte for byte |
The request body is not compared on replay. A request that reuses a key within 24 hours receives the cached response even if its payload differs from the original request. After the 24-hour lifetime the key expires, and a request that reuses it executes as a new operation.
Never reuse a key for a different operation. A duplicate key returns the original operation's cached response, and the second operation is silently never performed.
If the cache backing idempotency is unavailable, the API rejects idempotent requests with 503 Service Unavailable and error code SERVICE_001 rather than risking a duplicate execution.
Concurrent Requests
When a duplicate request arrives while the original request with the same key is still executing:
- The duplicate waits up to 5 seconds for the original to complete, then returns the cached response.
- If the original has not completed within that window, the duplicate is rejected with
409 Conflictand error codeCONFLICT_001. Retrying with the same key after the original completes returns the cached response.
{
"success": false,
"status": 409,
"error": {
"code": "CONFLICT_001",
"message": "A request with this Idempotency-Key is currently being processed. Please retry shortly.",
"doc_url": "https://docs.sent.dm/reference/api/idempotency"
},
"meta": { ... }
}Response Headers
Idempotent-Replayed
When a cached response is returned, the Idempotent-Replayed: true header is included:
HTTP/1.1 201 Created
Idempotent-Replayed: true
X-Original-Request-Id: req_original_abc123
X-Request-Id: req_replay_def456
Content-Type: application/json
{
"success": true,
"data": { ... },
"error": null,
"meta": { ... }
}Header Reference
| Header | Description |
|---|---|
Idempotent-Replayed | true if this is a cached response |
X-Original-Request-Id | Request ID of the original request |
X-Request-Id | Request ID of the current request |
Idempotency vs Sandbox Mode
Both features help with safe API usage, but serve different purposes:
| Feature | Purpose | Side Effects | Response |
|---|---|---|---|
| Sandbox Mode | Validate requests | None (validation only) | Fake/sample data |
| Idempotency | Prevent duplicates | Only on first request | Real/cached data |
The two features can be combined in one request: a sandbox: true payload sent with an Idempotency-Key is validated without side effects, and its response is cached and replayed like any other. Refer to the Sandbox Mode reference for the sandbox contract.
Related guides
- How to retry Sent API requests safely: key derivation, retry loops that reuse keys,
CONFLICT_001handling, and a reusable client implementation. - How to handle Sent API errors: error envelope handling in client code.
Roles and Permissions
How Sent's four user roles control access to Sent API v3 operations and dashboard sections, and which checks produce AUTH_004 errors
Sandbox Mode
The sandbox request field in the Sent API v3: validation behavior, supported endpoints and their simulated responses, the X-Sandbox header, and troubleshooting.