Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.have-foresight.app/llms.txt

Use this file to discover all available pages before exploring further.

The Foresight RCM API supports idempotency on every mutating endpoint (POST, PUT, PATCH). Pass an Idempotency-Key header and the API guarantees that retrying the same request will return the same result — no duplicate claims, no duplicate prior auths, no duplicate webhook fires.

How to use it

Generate a unique key per logical operation. A UUID v4 is the simplest choice:
curl -X POST "$FORESIGHT_BASE_URL/claims" \
  -H "X-API-Key: $FORESIGHT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{ ... }'
If the API has seen this key before for the same endpoint:
  • The original response is replayed — same status code, same body, same requestId.
  • No side effects re-run (no duplicate DB writes, no duplicate clearinghouse submissions, no duplicate webhook fires).
If the API hasn’t seen the key, the request runs normally and the response is cached against the key.

Key requirements

  • Maximum length: 255 characters.
  • Must be unique per logical operation (not per HTTP retry).
  • Cached for 24 hours after the first request. Reusing a key after 24 hours executes the request fresh.

Body mismatch

If you reuse an idempotency key with a different request body, the API returns 409 idempotency_key_mismatched_body. Treat this as a programming error — generate a new key for the new operation.

When the cached response is in flight

If two requests with the same key arrive simultaneously, the second returns 409 idempotency_key_in_use. Retry after a short delay (the first request will complete and cache its result).

When NOT to send a key

GET requests are inherently idempotent and ignore the header. DELETE is also idempotent at the resource level (deleting an already-deleted resource is a no-op 204) so the header is unnecessary but accepted. Generate the key in your code before the request, and persist it alongside the operation in your own DB. On retry, look up the persisted key rather than generating a new one.
async function submitClaim(draft) {
  // Look up or create the key for this draft
  let key = await db.idempotencyKeys.findByDraftId(draft.id);
  if (!key) {
    key = crypto.randomUUID();
    await db.idempotencyKeys.create({ draftId: draft.id, key });
  }

  return fetch(`${BASE}/claims`, {
    method: 'POST',
    headers: {
      'X-API-Key': API_KEY,
      'Content-Type': 'application/json',
      'Idempotency-Key': key,
    },
    body: JSON.stringify(draft),
  });
}

What’s protected

OperationIdempotent?Notes
POST /v1/claimsYesSame key → same claim, no duplicate submission
POST /v1/prior-authorizationsYesSame key → same PA, no duplicate payer call
POST /v1/insurance-policies/validateYesCached eligibility response replayed
POST /v1/appeals/{id}/sendYesLetter delivered exactly once
POST /v1/webhooks/subscriptionsYes
PATCH /v1/patients/{id}YesSame body produces same final state
DELETE /v1/{any}YesInherently idempotent