Lucius API

Idempotency

How the API handles duplicate requests and ensures safe retries.

Usage event submissions are idempotent. You can safely retry failed requests without creating duplicate events or charges.

How it works

Each usage event requires a unique event_id field. This serves as the idempotency key:

{
  "events": [{
    "external_contract_id": "acme-corp-2026",
    "event_id": "inv-12345-2026-03",
    "metric": "revenue_amount_invoiced",
    "quantity": 15000,
    "timestamp": "2026-03-15T00:00:00.000Z"
  }]
}

If you submit the same event_id twice:

  • The first request creates the event and rates it
  • The second request returns status: "accepted" without creating a duplicate
  • The invoice is not double-charged

Choosing event IDs

Use a deterministic ID that uniquely identifies the business event:

PatternExampleWhen to use
Invoice referenceinv-12345-2026-03Billing on invoice amounts
Transaction IDtxn-abc123Billing on payment volume
Date-baseddaily-revenue-2026-03-15Daily aggregated metrics
UUID550e8400-e29b-41d4-a716-446655440000When no natural key exists

Avoid random IDs if you need to retry — you won't be able to reconstruct the same ID.

Retry strategy

For transient failures (HTTP 500, timeouts, network errors):

  1. Retry with the same event_id
  2. Use exponential backoff (1s, 2s, 4s, 8s)
  3. Cap at 3–5 retries
  4. The API will deduplicate automatically
async function submitWithRetry(event: UsageEvent, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const res = await fetch("https://api.lucius.finance/v1/billing/usage", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ events: [event] }),
      });
      if (res.ok) return await res.json();
      if (res.status < 500) throw new Error(`Client error: ${res.status}`);
    } catch (e) {
      if (attempt === maxRetries) throw e;
      await new Promise((r) => setTimeout(r, 1000 * 2 ** attempt));
    }
  }
}

Scope

Idempotency keys are scoped to your company. Different companies can use the same event_id without conflict.

The key is permanent — once an event_id is used, it cannot be reused for a different event, even after the original event is rated.

On this page