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

  1. The client generates a unique key for each distinct operation
  2. The client sends it in the Idempotency-Key header
  3. The API caches the successful response for 24 hours
  4. 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.

ConditionBehavior
POST, PUT, or PATCH to /v3/* with Idempotency-KeyIdempotency processing applies
POST, PUT, or PATCH without Idempotency-KeyRequest executes normally; the header is optional
GET or DELETE requestThe 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-doe

Invalid Examples

req abc 123       # Contains spaces
create@contact    # Contains special character @
send.msg.001      # Contains periods

Response Caching

RuleBehavior
Cached responsesOnly successful (2xx) responses are cached
Error responsesNot cached, so a retry with the same key executes the request again
Cache lifetime24 hours from the original response
Response size limitResponses larger than 5 MB are not cached; duplicates execute again
Replayed contentThe 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 Conflict and error code CONFLICT_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

HeaderDescription
Idempotent-Replayedtrue if this is a cached response
X-Original-Request-IdRequest ID of the original request
X-Request-IdRequest ID of the current request

Idempotency vs Sandbox Mode

Both features help with safe API usage, but serve different purposes:

FeaturePurposeSide EffectsResponse
Sandbox ModeValidate requestsNone (validation only)Fake/sample data
IdempotencyPrevent duplicatesOnly on first requestReal/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.


On this page