Skip to main content
Docs

Search guides and API endpoints, for example “Idempotency-Key” or “submit job”.

    Guides

    Retry safely

    A retry loop that never starts the same job twice, with plain HTTP and with the Python SDK.

    Updated October 1, 2026

    On this page

    Networks fail. If a submit times out, you can't tell whether the job was queued. The fix is to create the Idempotency-Key once per job and send the same key on every retry: if the first attempt went through, the retry returns its result instead of queuing a second job. Idempotency has the rules.

    Plain HTTP (Python with httpx)

    import os
    import random
    import time
    import uuid
     
    import httpx
     
    API = "https://api.cognichem.com/api/v1"
    HEADERS = {"X-Api-Key": os.environ["COGNICHEM_API_KEY"]}
    RETRY = {"upstream", "timeout", "quota"}
     
     
    def submit(job, attempts=5):
        key = str(uuid.uuid4())  # one key for this job, reused on every retry
        for attempt in range(attempts):
            try:
                response = httpx.post(
                    f"{API}/jobs/submit",
                    json=job,
                    headers={**HEADERS, "Idempotency-Key": key},
                    timeout=30,
                )
            except httpx.TransportError:
                pass  # no response: safe to retry with the same key
            else:
                if response.status_code < 400:
                    return response.json()["process_id"]
                problem = response.json()
                if response.status_code != 409 and problem.get("retryability") not in RETRY:
                    raise RuntimeError(f"{problem['status']} {problem.get('detail')}")
                # 409: the first attempt is still in progress; wait and retry the same key.
            time.sleep(min(30, 2**attempt) + random.random())
        raise RuntimeError("gave up after retries")

    With the Python SDK

    The SDK sends a new key on every call, so for a retry loop pass your own:

    import uuid
     
    from cognichem_client import CogniChem
    from cognichem_client.errors import CogniChemError
     
    client = CogniChem.from_env()
    key = str(uuid.uuid4())
     
    for attempt in range(5):
        try:
            job = client.jobs.submit(
                job_name="padel-batch-7",
                job_type="padel-descriptor",
                payload={"input_data": ["CCO"], "input_format": "smiles"},
                idempotency_key=key,
            )
            break
        except CogniChemError as error:
            if error.retryability not in {"upstream", "timeout", "quota"}:
                raise

    Don'ts

    • Don't build the key from the payload: two jobs you mean to run separately would collide, and the second would quietly return the first.
    • Don't reuse a key with a changed body. That returns 409, not a second job.
    • Don't retry validation or auth errors unchanged; fix the request first (Handling errors).