POST that times out leaves you guessing: the alert, webhook connection, or transcription request may already exist. Send an Idempotency-Key header with the write, resend the same key on every retry, and the request runs at most once. A retry gets the first response back, so you can retry a write the same way you retry a read.
Send a key
Generate one key per logical write, such as a UUID, before the first attempt, and reuse it for every retry of that write:$KEY and you get the first response back, with Idempotent-Replayed: true, and no second alert. Mint a new key for a new write: a key belongs to one request.
A key is 8 to 128 printable ASCII characters. The header is optional; a write sent without it behaves as it always has.
Endpoints that take a key
Each of these carries
x-idempotent: true and the Idempotency-Key header parameter in the OpenAPI document, so a generated client can find them. Other endpoints ignore the header. Reads are already safe to retry, and an alert update or a delete can simply be sent again.
What a retry gets back
A request is the same when its method, path, query string, and body bytes all match. Resend the body exactly as you first sent it rather than rebuilding it.
A success is replayed for 24 hours. After that the key is forgotten, and a request under it runs as new.
Scope
A key belongs to the API key that sent it. Two API keys can use the same key string without colliding, and one project’s key can never replay another project’s response. A revoked key gets401 on its retries like on any other request. The header is ignored on a keyless x402 request, which has no credential to hold a key, and on a signed-in session at platform.particle.pro, whose access to a project can be withdrawn while a key is still being replayed.
Limits
- An organization can start 50,000 keyed writes in 24 hours. Past that, a request with a new key gets
429rate_limit_exceededwithRetry-Afterand does not run. Retries of keys already in use still get their answers, and requests without a key are unaffected. - If we cannot check the key, the request does not run. A
503withRetry-Aftermeans the key could not be looked up, so the write was refused rather than run unrecorded. Retry with the same key. - A failure on our side can still run a write twice. If our server stops, or loses the store that records keys, after the write commits but before its response is recorded, a retry gets
409 idempotency_key_in_useuntil shortly after the request’s own time limit, and a retry after that runs the write again. This takes a failure on our side at one exact moment; a timeout or a dropped connection on your side does not cause it. - MCP tool calls do not take a key. The
particle_alert_*tools on the MCP server run without one; check withparticle_alert_listbefore creating an alert again.
id. See Delivery, retries, and idempotency.