Idempotency

Networks fail. Servers restart. AltFiScore supports idempotent API calls so your application can safely retry requests without creating duplicate decisions or duplicate applications.

How it works

Include an Idempotency-Key header on any state-changing request. AltFiScore caches the response for 24 hours. Any subsequent request with the same key — even if the network failed and you retry — returns the cached response instead of creating a new decision.

HTTP header

POST /v1/decisions/bnpl HTTP/1.1
Authorization: Bearer altfi_test_YOUR_KEY
Content-Type: application/json
Idempotency-Key: bnpl-2026-05-15-checkout-7f3a9b21

Key format

Idempotency keys are free-form strings up to 255 characters. Use any format that's unique to the operation you're performing:

  • UUIDs — simplest, works everywhere: crypto.randomUUID()
  • Composite keys — embed business context: checkout-{cart_id}-{timestamp}
  • Hashed inputs — deterministic from the request body

Recommended

Use UUIDs for simplicity. They guarantee uniqueness without coordination, and most languages have a one-liner to generate them.

Retry behavior

AltFiScore matches incoming requests against the idempotency cache as follows:

  • Same key, same request body → returns the cached response immediately. The cached response is byte-identical to the original, including decision_id.
  • Same key, different request body → returns HTTP 409 Conflict with error: "idempotency_conflict". The key is considered "claimed" by the first request.
  • New key → request is processed normally and the response is cached.
  • No key → request is processed normally with no caching. Not recommended for state-changing operations.

Don't reuse keys across logical operations

An idempotency key represents one logical operation. Reusing a key for a different purpose will either return a stale cached response (worst case: you display the wrong decision to a different consumer) or trigger a 409 conflict. Always generate a fresh key for a new logical operation.

Cache duration

Idempotency entries are cached for 24 hours from the time of the original request. After that, the key is forgotten and a retry with the same key creates a new decision.

For most use cases — checkout flows, webhook retries, background job retries — 24 hours is far more than enough.

Recommended retry pattern

Combine an idempotency key with exponential backoff for resilient retries:

Node.js

async function decideWithRetry(body, maxAttempts = 5) {
  const idempotencyKey = crypto.randomUUID()
  let attempt = 0

  while (attempt < maxAttempts) {
    try {
      const res = await fetch('https://api.altfiscore.com/v1/decisions/bnpl', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${process.env.ALTFISCORE_API_KEY}`,
          'Content-Type': 'application/json',
          'Idempotency-Key': idempotencyKey,
        },
        body: JSON.stringify(body),
      })
      if (res.ok) return await res.json()

      // 4xx errors (except 429) shouldn't be retried
      if (res.status >= 400 && res.status < 500 && res.status !== 429) {
        throw new Error(`Client error: ${res.status}`)
      }
    } catch (err) {
      if (attempt === maxAttempts - 1) throw err
    }

    attempt += 1
    await sleep(Math.min(2 ** attempt * 100, 5000))  // exp backoff, max 5s
  }
}

Because the idempotency key is generated once at the start and reused across all retries, AltFiScore guarantees that no matter how many times the network fails, you'll get at most one decision created.

When to use idempotency

  • Always on state-changing operations (POST endpoints). The cost of including a header is zero; the cost of an accidental duplicate decision can be significant.
  • Not needed on read-only operations (GET endpoints) — they're naturally idempotent.

Next steps