BanklyzeBanklyze/Developer Docs
Sign In

Idempotency

Network errors and timeouts can leave you uncertain whether a request succeeded. Retrying a POST request without an idempotency key can create duplicate resources — two deals for the same applicant, or a document uploaded twice. The Banklyze API supports idempotency keys so you can safely retry any creation request without risk of duplication.

How It Works

Include the Idempotency-Key header with a unique value in your POST request. The API stores the response for that key for 24 hours. If you send the same key again within that window, the API returns the original stored response immediately — without creating a new resource or running the operation again.

  1. Generate a unique key (UUID v4 recommended) before making the request.
  2. Include it as Idempotency-Key: <your-uuid> in the request headers.
  3. If the request times out or you receive a network error, retry the exact same request with the same key.
  4. The API returns the original response — the resource is not created twice.
First request creates — subsequent requests with same key replay
# First request — resource created
HTTP/2 201 Created
Idempotency-Key: 7f3d9a2b-1c4e-4f8a-9b0d-2e5f6a7c8d9e

{
  "id": 99,
  "business_name": "Acme Trucking LLC",
  "status": "new",
  "created_at": "2026-03-04T10:00:00Z"
}

# Second request — same Idempotency-Key, same response returned immediately
HTTP/2 200 OK
Idempotency-Key: 7f3d9a2b-1c4e-4f8a-9b0d-2e5f6a7c8d9e

{
  "id": 99,
  "business_name": "Acme Trucking LLC",
  "status": "new",
  "created_at": "2026-03-04T10:00:00Z"
}

Supported Endpoints

Idempotency keys are supported on write endpoints that create new resources. GET, PATCH, and DELETE requests are naturally idempotent and do not require or use idempotency keys.

NameTypeRequiredDescription
POST /v1/ingestsupportedOptionalBulk CRM ingest. Use a stable batch ID or content hash as the key to safely retry failed batch imports without duplicating deals.
POST /v1/dealssupportedOptionalCreate a new deal. Use a UUID derived from the applicant record in your system so retries never create a duplicate deal.
POST /v1/deals/{id}/documentssupportedOptionalUpload a document. Derive the key from the file hash or your internal document ID to prevent duplicate uploads.
GET /v1/*naturalOptionalAll GET endpoints are naturally idempotent — reading data never has side effects. No key needed.
PATCH /v1/*naturalOptionalPATCH endpoints apply the same change regardless of how many times they are called with the same body. No key needed.
DELETE /v1/*naturalOptionalDELETE endpoints are idempotent — deleting an already-deleted resource returns 404, not an error. No key needed.

Examples

curl — create a deal

curl — POST /v1/deals with Idempotency-Key
# The -H "Idempotency-Key: $(uuidgen)" flag generates a fresh UUID on macOS/Linux.
# Store the key if you may need to retry the same request.

IDEM_KEY=$(uuidgen)

curl -X POST https://api.banklyze.com/v1/deals \
  -H "X-API-Key: bk_your_api_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $IDEM_KEY" \
  -d '{
    "business_name": "Acme Trucking LLC",
    "entity_type": "llc",
    "funding_amount_requested": 75000
  }'

Python — create a deal with retry

Python — idempotent deal creation with retry loop
import os
import uuid
import requests

API_KEY = os.environ["BANKLYZE_API_KEY"]
BASE_URL = "https://api.banklyze.com/v1"


def create_deal(business_name: str, funding_amount: float) -> dict:
    """Create a deal with an idempotency key to prevent duplicates on retry."""
    idempotency_key = str(uuid.uuid4())

    payload = {
        "business_name": business_name,
        "funding_amount_requested": funding_amount,
    }

    # Retry loop — safe to retry because of the idempotency key
    for attempt in range(3):
        try:
            resp = requests.post(
                f"{BASE_URL}/deals",
                headers={
                    "X-API-Key": API_KEY,
                    "Idempotency-Key": idempotency_key,
                },
                json=payload,
                timeout=30,
            )
            resp.raise_for_status()
            return resp.json()
        except requests.exceptions.Timeout:
            if attempt == 2:
                raise
            print(f"Timeout on attempt {attempt + 1}, retrying with same key...")

    raise RuntimeError("All retries failed")


deal = create_deal("Acme Trucking LLC", 75000)
print(f"Created deal {deal['id']}: {deal['business_name']}")

Python — bulk ingest

Python — idempotent bulk ingest
import os
import uuid
import requests

API_KEY = os.environ["BANKLYZE_API_KEY"]
BASE_URL = "https://api.banklyze.com/v1"


def bulk_ingest(applications: list[dict]) -> dict:
    """Ingest multiple applications safely — idempotency key prevents duplicates."""
    # Generate a stable key for this batch. If you use a content hash or
    # batch ID, the key will be the same on retry, deduplicating automatically.
    batch_id = str(uuid.uuid4())

    resp = requests.post(
        f"{BASE_URL}/ingest",
        headers={
            "X-API-Key": API_KEY,
            "Idempotency-Key": batch_id,
        },
        json={"applications": applications},
        timeout=60,
    )
    resp.raise_for_status()
    return resp.json()


# Sending twice with the same key returns the original response — no duplicate
batch = [
    {"business_name": "Sunrise Bakery Inc", "external_ref": "CRM-001"},
    {"business_name": "Metro Auto Parts", "external_ref": "CRM-002"},
]
result = bulk_ingest(batch)
print(f"Ingested {result['created']} new, {result['skipped']} skipped")

curl — upload a document

curl — POST /v1/deals/{id}/documents with Idempotency-Key
# Upload a document with an idempotency key.
# Reusing the same key for the same file prevents a duplicate upload.

IDEM_KEY=$(uuidgen)  # Or derive from file hash: sha256sum statement.pdf | cut -d' ' -f1

curl -X POST "https://api.banklyze.com/v1/deals/42/documents" \
  -H "X-API-Key: bk_your_api_key" \
  -H "Idempotency-Key: $IDEM_KEY" \
  -F "file=@/path/to/statement.pdf" \
  -F "document_type=bank_statement"
Derive keys from content when possible. For document uploads, compute the SHA-256 hash of the file and use it as the idempotency key. This guarantees that retrying the exact same file never creates a duplicate, even across process restarts.

Key Expiration

Idempotency keys expire 24 hours after the original request. After expiration:

  • Sending the same key creates a new resource as if the key had never been used.
  • The cached response for the key is discarded.

This means you can safely reuse a key after 24 hours for a genuinely new request, though generating a fresh UUID is the recommended practice.

NameTypeRequiredDescription
Idempotency-KeyheaderOptionalAny unique string up to 255 characters. UUID v4 format is strongly recommended (e.g. 7f3d9a2b-1c4e-4f8a-9b0d-2e5f6a7c8d9e).
Key TTL24 hoursOptionalCached responses are retained for 24 hours from the original request time. After that, the key is treated as new.

Error Handling

If the original request failed with a 4xx or 5xx error, the idempotency key is not consumed. You can retry with the same key and the request will be processed normally — it will not replay the error response.

NameTypeRequiredDescription
Original: 2xxreplayedOptionalThe stored response is returned immediately. The operation is not repeated.
Original: 4xxnot consumedOptionalThe key is discarded after a client error. Retry with the same key after fixing the issue — the request runs normally.
Original: 5xxnot consumedOptionalThe key is discarded after a server error. Retry with the same key — safe to do immediately or after backoff.
Original: network timeoutsafe to retryOptionalIf you never received a response, retry with the same key. If the original succeeded server-side, the replay is returned. If it never ran, it runs now.
Never reuse a key for a different request body. If you send the same Idempotency-Key with a different payload, the API returns the original cached response — not the result you intended. Always generate a new UUID for each distinct resource you want to create.
bash — why reusing keys for different bodies is dangerous
# WRONG — reusing the same key for a different request body
SHARED_KEY="7f3d9a2b-1c4e-4f8a-9b0d-2e5f6a7c8d9e"

# First request: creates deal for "Acme Trucking LLC"
curl -X POST https://api.banklyze.com/v1/deals \
  -H "Idempotency-Key: $SHARED_KEY" \
  -d '{"business_name": "Acme Trucking LLC"}'

# Second request: WRONG — different body, same key.
# The API will return the ORIGINAL "Acme Trucking LLC" response,
# NOT create "Sunrise Bakery Inc".
curl -X POST https://api.banklyze.com/v1/deals \
  -H "Idempotency-Key: $SHARED_KEY" \
  -d '{"business_name": "Sunrise Bakery Inc"}'

# CORRECT — always generate a new UUID for a different resource
curl -X POST https://api.banklyze.com/v1/deals \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"business_name": "Sunrise Bakery Inc"}'