DynVoltDYNVOLT · developers

Idempotency

Safe write retries with the Idempotency-Key header.

Network calls fail in ambiguous ways: a timeout after a POST /work-orders leaves you unsure whether the work order was created. The Idempotency-Key header makes write retries safe.

How it works

Send a unique key (a UUID is ideal) with any write request:

curl -X POST "https://api.owner.dynvolt.com/v1/sites/pv-ljubas/defects" \
  -H "Authorization: Bearer $DYNVOLT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0d6a9c42-3f1e-4d5b-9a8c-7e6f5d4c3b2a" \
  -d '{"title": "Cracked module, row 14", "severity": "low"}'
  • The first request with a given key executes normally, and the response is recorded against the key.
  • Any retry with the same key and the same body within 24 hours does not execute again — it replays the recorded response, byte for byte.
  • After 24 hours the key expires and may be reused.

The header is optional. Requests without it execute unconditionally, every time.

Conflicts

Reusing a key with a different body is rejected with 422 and error code idempotency_conflict:

{
  "error": {
    "code": "idempotency_conflict",
    "message": "Idempotency-Key was already used with a different request body.",
    "request_id": "req_5c1d9e2f7b",
    "details": null
  }
}

This is a bug guard, not a retry signal: it means your client generated the same key for two different requests. Generate a fresh key per logical operation — not per HTTP attempt, and never a constant.

import uuid

def create_work_order(client, site_id, payload):
    key = str(uuid.uuid4())          # one key per logical operation
    for attempt in range(5):
        try:
            resp = client.post(
                f"/v1/sites/{site_id}/work-orders",
                headers={"Idempotency-Key": key},   # same key on every retry
                json=payload,
                timeout=15,
            )
            if resp.status_code < 500:
                return resp
        except Exception:
            pass  # timeout / connection error: retry with the SAME key
    raise RuntimeError("work order creation failed after retries")

Which endpoints support it

All write endpoints accept Idempotency-Key:

  • POST /v1/sites/{site_id}/work-orders, PUT .../work-orders/{item_id}, POST .../work-orders/{item_id}/approve
  • POST /v1/sites/{site_id}/defects, PUT .../defects/{item_id}
  • POST .../alerts/{item_id}/acknowledge, POST .../alerts/{item_id}/resolve
  • POST .../reports/subscriptions/{item_id}/run

Reads are naturally idempotent and ignore the header.