Skip to main content
Documentation

Guide

Idempotency

Every capability declares what a repeat of the same call does — and only one of the three answers needs a key from you.

Retries are normal. A timeout does not tell you whether the work happened, and a queue that gives up too early is worse than one that retries. So every capability declares, on its own page, which of three things a repeat does.

DeclaredWhat a repeat doesWhat you should do
naturalRunning it twice leaves the same world as running it once — a read, or a write that SETS a value rather than appending one.Retry freely. No key needed, and passing one buys nothing.
keyA repeat is not harmless, and this capability honours an idempotency key.Send a stable Idempotency-Key header. A retry replays the first answer instead of acting again.
noneA repeat genuinely does it twice and no key can make it not.Read the current state first. The capability's operating contract names what to read.
A retry that replays instead of acting twice
curl -X POST $SERVICEVIN_ORIGIN/api/v1/quotes/send \
  -H "Authorization: Bearer $SERVICEVIN_API_KEY" \
  -H "Idempotency-Key: quote-9b2f1c6e-attempt-1" \
  -H "Content-Type: application/json" \
  -d '{"quote_id":"9b2f1c6e-4a77-4d2b-9f31-0f1c9a8e5d20"}'

A key is a promise this end makes, never a demand on the caller

It is optional everywhere, including over MCP — and especially over MCP. A model asked to invent an idempotency key would invent a different one on every call, which buys nothing and looks like it bought something.

The key is matched per shop and per capability, and only a call that SUCCEEDED is replayable. A first attempt that was refused — by a gate, by validation, by the rate limiter — leaves nothing to replay, so the retry is a fresh attempt.