Idempotency Keys
Prevent duplicate records from retried API requests
Overview
Retried API requests can create duplicate records or trigger duplicate side effects. Idempotency keys solve this by caching the original response and replaying it when the same key is used again.
Idempotency keys are supported on all POST, PUT, PATCH, and DELETE
requests. They are optional but strongly recommended for all mutating
Public Data API actions.
How It Works
- Client sends a request with an
Idempotency-Keyheader - Server processes the request and stores the response keyed by the idempotency key
- If the same key is sent again with the same body, the cached response is returned
- If the same key is sent with a different body, a
409 Conflictis returned
Usage
Request
POST /api/v1/public/data HTTP/1.1
X-API-Key: ta_sk_xxxxxxxxxxxx
Idempotency-Key: f47ac10b-58cc-4372-a567-0e02b2c3d479
Content-Type: application/json
{
"action": "create-work-item",
"item_type": "job",
"title": "HVAC Maintenance - Building A",
"contact_id": 123,
"location_id": 456
}Response (First Request)
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 2026-07-22T12:01:00Z
{
"success": true,
"data": {
"id": 12345,
"item_number": "JOB-2026-0001",
"title": "HVAC Maintenance - Building A"
}
}Response (Replay)
HTTP/1.1 200 OK
X-Idempotent-Replay: true
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 2026-07-22T12:01:00Z
{
"success": true,
"data": {
"id": 12345,
"item_number": "JOB-2026-0001",
"title": "HVAC Maintenance - Building A"
}
}Key Format
- UUID v4 (recommended):
f47ac10b-58cc-4372-a567-0e02b2c3d479 - Arbitrary string: Up to 255 characters, unique per client
Conflict Handling
If the same key is reused with a different request body, the server returns:
{
"success": false,
"error": {
"code": "IDEMPOTENCY_CONFLICT",
"message": "Idempotency key was already used with a different request body",
"documentation_url": "https://dev-developer.totalaccess.co.za/docs/api-reference/errors#idempotency_conflict"
}
}Expiration
Idempotency keys expire after 24 hours. After expiration, the key can be reused with any request body.
Webhook Delivery
Outbound webhook deliveries include an Idempotency-Key header containing the
event UUID. This allows webhook receivers to deduplicate redelivered events:
POST /your-webhook-endpoint HTTP/1.1
Idempotency-Key: evt_550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
{
"event": "job.completed",
"timestamp": "2026-07-22T14:30:00Z",
"data": { ... }
}Supported Actions
All mutating Public Data API actions support idempotency keys:
| Action | Scope |
|---|---|
create-work-item | work_items:write |
create-appointment | appointments:write |
create-comment | comments:write |
create-recurring-job | recurring:write |
update-recurring-job | recurring:write |
pause-recurring-job | recurring:write |
resume-recurring-job | recurring:write |
generate-recurring-job | recurring:write |
send-thread-message | threads:send_message |
Best Practices
- Generate a new UUID for each unique request — never reuse keys across different operations
- Store the key alongside your request — so retries use the same key
- Handle
409 Conflictgracefully — it means the key was already used with different data - Don't rely on idempotency for reads —
GETrequests are inherently idempotent