ThrustLab

Idempotency

The SDK auto-generates an Idempotency-Key header (UUID v4) on every POST, PUT, PATCH, and DELETE request. If a network blip causes you to retry, the second request lands on the same key as the first — the server returns the original response instead of double-creating.

You only need to think about idempotency keys when you want end-to-end idempotency across your own retries, not just the SDK's internal ones.

Auto-generated keys (the default)

from thrustlab import Client

client = Client()
sim = client.simulations.create(project_id="proj_xxx", ...)

Behind the scenes:

  1. The SDK generates a UUID v4 (Idempotency-Key: 7b9...).
  2. If the request fails on a retryable error (429/5xx/network), the same key is reused on every retry.
  3. The server stores (key, request_body_hash, response) for 24 hours. Replays of an exact match return the cached response.

This makes the SDK safe under any transient failure without any work from you.

Explicit keys (end-to-end idempotency)

When your own orchestrator might re-run a job after a crash or a queue re-delivery, pass an explicit key tied to your job's identity. That way, re-running the job lands on the same server-side record, even from a fresh process with a fresh SDK client.

sim = client.simulations.create(
    project_id="proj_xxx",
    battery_component_id="comp_batt_xxx",
    airspeed_m_s=0.0, density_kg_m3=1.225, battery_charge_pct=100,
    rotor_groups=[{
        "label": "main", "count": 4,
        "motor_component_id": "comp_motor_xxx",
        "propeller_component_id": "comp_prop_xxx",
        "throttle_pct": 70,
    }],
    idempotency_key="job-2026-04-28-sim-001",  # tied to your job id
)

Every mutation method on every resource accepts idempotency_key=:

project = client.projects.create(name="Q3 study", idempotency_key="job-2026-04-28-proj")
client.projects.update("proj_xxx", name="Q3 study v2", idempotency_key="job-2026-04-28-rename")
endpoint = client.webhook_endpoints.create(
    url="https://...", events=["simulation.completed"],
    idempotency_key="setup-2026-04-28",
)

Key requirements

  • Unique per logical operation. Reusing the same key for a different intent (a different request body) fails with a 409 idempotency_error, code idempotency_key_reused_with_different_body.
  • Up to 255 characters. UUIDs, KSUIDs, and "job-id-step-name" patterns all work. Random strings are fine.
  • Valid for 24 hours. After 24 hours the server forgets the key; reusing it then is treated as a fresh request.

What "same response" means

The server replays the response byte-for-byte within the 24-hour window — including HTTP status, headers, and body. So if the original returned 201 Created with a freshly-minted resource, every replay returns that same resource id and the same body. This is the contract you're relying on when retrying after a network blip.

Recipe: idempotent fan-out from a queue worker

from thrustlab import Client

client = Client()

def handle_job(job):
    """Submit a sim from a queue job. Re-deliveries are safe."""
    sim = client.simulations.create(
        project_id=job["project_id"],
        idempotency_key=f"sim-from-job-{job['id']}",
        **job["params"],
    )
    return sim["id"]

If the queue redelivers job (because the worker crashed before ack), the second call returns the same sim resource — no double-charge.

See also

We use cookies and analytics tools to understand how you use ThrustLab and improve the experience. Privacy Policy

Python SDK — Idempotency · ThrustLab API