Ingram Cloud

Documentation

Extraction

Extraction

POST /v1/extract returns typed values from one input: a text span with its offsets, a number read or computed, a date, a duration, a list, an estimate with an interval, or a short forecast. Each value comes with a confidence and the probability that the input does not determine it. It runs Cloudflare's Clairic, an extraction model that answers in one forward pass and generates no tokens. Use it to pull fields out of invoices, receipts and emails, compute a total or a day count, price a listing from comparables, or forecast a daily series, without running a conversation.

The call is metered like any model op. Nothing is stored.

Models

ModelInputKey
cloudflare.clairictext and up to 4 imagesyour project's Cloudflare key only

model is required and must be the namespaced id. Clairic is a preview checkpoint on Cloudflare Workers AI; Cloudflare's model page documents the body field for field, and this endpoint takes it unchanged.

Extract values

# Authorization: tenant-admin token (server-side only)
curl https://api.cloud.ingram.tech/v1/extract \
  -H "Authorization: Bearer $IC_TOKEN" \
  -H "IC-Api-Version: 2026-05-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "cloudflare.clairic",
    "state": "Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. 4 pallets at $250.00 each, shipping $80.00. Contact: Dana Ruiz, Priya Shah.",
    "fields": {
      "invoice_number": { "type": "text" },
      "due_date": { "type": "date", "instructions": "Issue date plus the net payment days" },
      "total": { "type": "number", "decimals": 2, "unit": "USD", "instructions": "Amount due including shipping" },
      "contacts": { "type": "list", "items": "text" },
      "po_number": { "type": "text", "instructions": "Purchase order number" },
      "days_to_pay": { "type": "estimate", "min": 0, "max": 120, "step": 1, "instructions": "Days after issue until this invoice is paid" }
    }
  }'

With the TypeScript SDK:

import { IngramCloud } from "@ingram-cloud/sdk/client";

const ic = new IngramCloud({ token: process.env.IC_TOKEN! });
const { answers } = await ic.extract.create({ model: "cloudflare.clairic", state, fields });

fields maps a name (^[A-Za-z_][A-Za-z0-9_.\-]{0,63}$) to a typed field. Every field takes instructions and null_threshold, the p_null above which value is null (default 0.5).

typeReturnsOptions
texta span of state, with span offsets
numbera number read or computedunit, integer, decimals 0 to 6
date, time, datetimean ISO valuereference_date on the request anchors dates without a year
durationa length of timeunit: seconds, minutes, hours, days, weeks, months, years
listmatching items in input order, with spansitems: text, number or date; decimals
estimatea value and its distribution inside [min, max]step (a number, "month", "year"), scale linear or log, unit
forecastone estimate per stepthe estimate options plus horizon 1 to 64 and interval: step, minute, hour, day, week, month, quarter, year

Fields in one request are answered independently against the same input. Clairic does one or two arithmetic steps; it does not chain long derivations or aggregate many table rows. Have it read the operands and let your code do the math.

Images

images takes up to 4 PNG, JPEG or WebP images, each a data URL or { "content_type", "base64" }, 4 MiB each. They are placed before state, which may then be empty. Remote URLs are refused.

"images": ["data:image/jpeg;base64,…"],
"fields": { "total": { "type": "number", "decimals": 2 }, "merchant": { "type": "text" } }

Read the answers

{
  "model": "cloudflare.clairic",
  "answers": {
    "invoice_number": { "type": "text", "value": "INV-2291", "span": [8, 16], "guess": "INV-2291", "confidence": 1, "p_null": 3.8e-10 },
    "due_date": { "type": "date", "value": "2026-10-02", "guess": "2026-10-02", "confidence": 0.9999, "p_null": 1.9e-08 },
    "total": { "type": "number", "value": 1080, "guess": 1080, "confidence": 0.9999, "p_null": 2.3e-08 },
    "contacts": { "type": "list", "value": ["Dana Ruiz", "Priya Shah"], "spans": [[120, 129], [131, 141]], "confidence": 0.9999 },
    "po_number": { "type": "text", "value": null, "guess": "INV-2291", "confidence": 0.9995, "p_null": 1 },
    "days_to_pay": { "type": "estimate", "value": 30, "mean": 29.535, "median": 30, "p10": 21, "p90": 38, "p_below": 5.9e-06, "p_above": 1.2e-05 }
  },
  "truncated": false,
  "usage": { "state_tokens": 61, "image_tokens": 0, "schema_tokens": 472, "input_tokens": 655, "output_tokens": 0, "passes": 3 }
}

value is the answer, or null when p_null passed the field's threshold. guess is the best value regardless of null_threshold, so a null answer still says what the model would have read. confidence is the model's confidence in guess. Estimates and forecasts carry median, p10 and p90; options: { "include_quantiles": true } adds 99 percentiles. Every answer is well formed; none is guaranteed correct. Route on confidence, p_null and the width of the interval, and send the low-confidence cases to a person or a conversation.

input_tokens includes schema_tokens, the tokens your field definitions cost. passes is how many parallel passes the fields were split across.

Limits & errors

The input is 65,536 tokens at most. One pass holds 8,192 tokens of state plus fields; fields that do not fit run in parallel passes that each see the whole input. The request body is 16 MiB at most, images 8 MiB decoded in total.

StatusCodeWhen
422invalid_requestThe body breaks the shape above. param names the field.
422model_kind_mismatchmodel is not an extraction model. A bare clairic is one.
422model_key_missingYour project has no Cloudflare key.
400model_request_failedCloudflare refused the request: a bad token, a limit above. The message carries Cloudflare's reason.
402budget_exceeded, card_required, insufficient_creditsAs for runs; only a project-wide budget applies. See Usage and Billing.
429rate_limit_exceededCloudflare is rate-limiting the key. Retry after the Retry-After seconds.
500extraction_failedAny other failure. 502 when Clairic answered in a shape this API does not know.

Keys

Clairic runs on your project's Cloudflare key only. Create a Workers AI token in the Cloudflare dashboard (Workers AI Read is enough) and note the account id. Add both in Settings → Models, or over the API, where the account id is workspace_id:

# Authorization: tenant-admin token (server-side only)
curl -X PUT https://api.cloud.ingram.tech/v1/tenant/model_keys/cloudflare \
  -H "Authorization: Bearer $IC_ADMIN_TOKEN" \
  -H "IC-Api-Version: 2026-05-01" \
  -H "Content-Type: application/json" \
  -d '{ "api_key": "<workers-ai-token>", "workspace_id": "<account-id>" }'
# → { "provider": "cloudflare", "configured": true, "base_url": null, "workspace_id": "<account-id>" }

A Cloudflare key without workspace_id is 422 workspace_id_required. Cloudflare bills the input tokens to your account; the platform fee is debited from your wallet at the Clairic price.

In the console

Settings → Models lists Cloudflare with the other providers; its row takes the Workers AI token and the account id.