Skip to content

Idempotency

Noticia gives you two complementary ways to make writes safe to repeat. Neither is mandatory, but using them makes your integration robust against retries and replays.

Every entity you push carries your own external_id (your CRM customer id, your POS ticket id, your SKU). Writes are upserts keyed on it: sending the same external_id twice updates the same entity instead of creating a duplicate.

  • POST /v1/profiles upserts by external_id.
  • POST /v1/sales-events recognizes a previously ingested external_id and does not double-write (it returns 200 instead of 201).
  • POST /v1/stores upserts by external_id.

This is the durable guarantee: it holds for the lifetime of the entity, not just for a short window. Always send a stable external_id.

For protection against a lost response (you sent the request, the network dropped the reply, and you do not know whether it landed), add an Idempotency-Key header, a unique value you generate such as a UUID v4:

Terminal window
curl https://api.sms.noticia.ai/v1/profiles \
-X POST \
-H "x-api-key: ntca_REPLACE_ME" \
-H "Idempotency-Key: 7f1c0b9e-2a4d-4c8e-9b1a-3e5f6a7b8c9d" \
-H "Content-Type: application/json" \
-d '{ "external_id": "crm-customer-4815", "first_name": "Camille" }'
  • First call: runs normally, and the response is stored against the key.
  • Replay (same key, same body): returns the original status and body, plus an Idempotent-Replayed: true header. The action does not run again.
  • Conflict (same key, different body): returns 409 with code: IDEMPOTENCY_CONFLICT. A key may only be reused for an identical request.

Keys are retained for 24 hours. After that, the same key runs as a fresh request.

The header is optional on every endpoint, including POST /v1/sales-events. It is a strongly recommended safety net for retries, not a requirement.

  • Always send a stable external_id. It is your permanent protection against duplicates.
  • Add an Idempotency-Key when you retry a write, and reuse the same key across retries of one operation (one key per logical operation, not per HTTP attempt).
  • On a replay, the body must match byte-for-byte. Serialize deterministically (stable key order) so a retry reproduces the exact same payload.
  • Persist the key alongside the operation so a process restart still retries with the original key.
  • Treat Idempotent-Replayed: true as a log signal that a retry was absorbed.
GoalUse
Never create a duplicate entity, everexternal_id (always)
Safely retry a write after a network errorIdempotency-Key (per retry)

Use both together: external_id for long-term identity, Idempotency-Key for safe network retries.