Idempotency
Make Ur Next Door API retries safe with the Idempotency-Key header: key format, 24 hour replay, conflicts, and code to generate keys in four languages.
If a request times out, you cannot know whether it worked. Sending it again might create a second post. The Idempotency-Key header solves this: send a unique key with each new request, and reuse it only when you retry that same request. The API then acts once, and answers every retry with the result of the first attempt.
How it works
- You send
POST /api/v1/postswithIdempotency-Key: 6f1c2b8e-.... - The post is created and the API stores the
2xxanswer for 24 hours, linked to that key. - You send the identical request again with the same key, within 24 hours. Nothing new is created. You get the stored answer, with the header
Idempotent-Replayed: true.
Only successful (2xx) answers are stored. If the first attempt failed (a 422, a 500, anything not 2xx), a retry with the same key runs the request again, so you can fix a problem and resend with the same key.
The rules
| Rule | Detail |
|---|---|
| Where | Any POST or DELETE. Ignored on GET. |
| Format | 1 to 64 characters: letters, digits, ., _, : or -. A UUID is ideal. Anything else answers 400 invalid_idempotency_key. |
| Lifetime | A stored answer replays for 24 hours. |
| Scope | Keys are remembered per API key. |
| Same key, different request | 422 idempotency_key_reused. A key belongs to one exact request: the same method, path and body. |
| Same key while the first is running | 409 idempotency_in_progress. Wait a moment and retry with the same key. |
Generate a key
IDEMPOTENCY_KEY=$(uuidgen)const idempotencyKey = crypto.randomUUID();import uuid
idempotency_key = str(uuid.uuid4())<?php
$idempotencyKey = bin2hex(random_bytes(16));Retry the right way
Create the key once per item, before the first attempt, and keep it for every retry of that item:
import os
import time
import uuid
import requests
api_key = os.environ["UND_API_KEY"]
payload = {"title": "Five easy ways to save water at home", "body": "<p>Small habits add up.</p>"}
key = str(uuid.uuid4()) # one key for this post, reused on every retry
for attempt in range(3):
try:
r = requests.post(
"https://urnextdoor.com/api/v1/posts",
headers={"Authorization": f"Bearer {api_key}", "Idempotency-Key": key},
json=payload,
timeout=30,
)
except requests.RequestException:
time.sleep(2 ** attempt)
continue
if r.status_code >= 500 or r.status_code == 409:
time.sleep(2 ** attempt)
continue
print(r.status_code, r.json())
breakWhen you create many items in a loop, make a new key for each item. Reusing one key for different posts answers 422 idempotency_key_reused.
Good keys from your own data
If your items already have a stable id (a spreadsheet row id, a database id), you can build the key from it, for example sheet-row-1042. Then even a workflow that runs twice by mistake within 24 hours cannot publish that row twice.
Next steps
- Errors, including which ones to retry.
- Rate limits and daily quotas.
- cURL.
Last updated