Skip to main content

Idempotency

Network calls fail in ambiguous ways — a request times out, but did the server process it? Retrying a create blindly risks a duplicate record. Idempotency keys make creates safely retryable.

How it works

Send an Idempotency-Key header with any create (POST) request:

curl -X POST https://papi.trendev.in/v1/contacts \
-H "Authorization: Bearer $PROSPECTCONNECT_TOKEN" \
-H "Version: 2026-06-01" \
-H "Idempotency-Key: 7e3b1c9a-2f4d-4a6b-9c8e-1d2f3a4b5c6d" \
-H "Content-Type: application/json" \
-d '{ "first_name": "Avery", "last_name": "Diaz", "email": "avery@example.com" }'
  • The first request with a given key is processed normally.
  • Any subsequent request with the same key returns the original result instead of creating a second record — so retrying after a timeout is safe.

The key is an arbitrary client-chosen string (up to 255 characters). Use something with enough entropy to be unique per logical operation — a UUID v4 is ideal.

When to use it

  • Always on creates you might retry (anything behind a flaky network, a queue, or a webhook handler).
  • Use one key per logical action — generate a fresh key for each distinct create, and reuse that same key only when retrying that create.
import uuid, requests

key = str(uuid.uuid4()) # one per logical create

def create_contact(body):
return requests.post(
"https://papi.trendev.in/v1/contacts",
headers={
"Authorization": f"Bearer {TOKEN}",
"Version": "2026-06-01",
"Idempotency-Key": key, # same key on every retry of THIS create
},
json=body, timeout=30,
)

Notes

  • Idempotency applies to creates. GET and DELETE are naturally idempotent; PATCH updates are applied as sent.
  • Don't reuse a key for a different payload — the safe contract is "same key ⇒ same original result."
  • For bulk imports, generate a deterministic key per source row (e.g. a hash of the row id) so re-runs of the import never double-insert.