Extract

Field types

Optional annotations that tell extraction what a field means — a currency, a phone number, a date — without changing the shape of the response.

View as Markdown

A schema field says what type a value has. A field type says what it is: {"type": "number"} could be a quantity or an amount of money, and {"type": "string"} could be a paragraph, a phone number, or a mailing address. Annotating it makes extraction better at reading it — and makes the in-app editors render it properly.

Annotations are optional. A schema with none behaves exactly as it does today, and every annotated schema is still plain, valid JSON Schema: standard format where one exists, and x-cr-* vendor keywords for the rest. A validator that has never heard of x-cr-* still reads the schema correctly.

The 13 field types

Field typeEmitted JSON SchemaMarked by
text{ "type": "string" }nothing — the bare type
long_text{ "type": "string", "x-cr-kind": "long_text" }x-cr-kind
number{ "type": "number" }nothing — the bare type
currency{ "type": "number", "x-cr-kind": "currency", "x-cr-currency": "CAD" }x-cr-kind (+ the x-cr-currency setting, omitted when unset)
boolean{ "type": "boolean" }nothing — the bare type
date{ "type": "string", "format": "date" }standard format
datetime{ "type": "string", "format": "date-time" }standard format
select{ "type": "string", "enum": ["a", "b"] }structure — enum
multi_select{ "type": "array", "items": { "type": "string", "enum": ["a", "b"] } }structure — an array of enum
email{ "type": "string", "format": "email" }standard format
phone{ "type": "string", "x-cr-kind": "phone" }x-cr-kind
url{ "type": "string", "format": "uri" }standard format
address{ "type": "string", "x-cr-kind": "address" }x-cr-kind

Only two vendor keywords exist: x-cr-kind, which names the field type, and x-cr-currency, a per-field setting for currency. Five field types need neither — date, datetime, email and url ride on standard JSON Schema format, and select / multi_select on enum.

Combine annotations with the rest of your schema as usual — nullability especially:

1{
2 "type": "object",
3 "properties": {
4 "total": { "type": ["number", "null"], "x-cr-kind": "currency", "x-cr-currency": "CAD" },
5 "due_date": { "type": ["string", "null"], "format": "date" },
6 "status": { "type": ["string", "null"], "enum": ["draft", "sent", "paid", null] }
7 }
8}

What annotations change, and what they don’t

They are hints, not shape changers. A currency value comes back as a number, not {"amount": …, "currency": …}. A date comes back as a string. A multi_select comes back as an array of strings. Strip every x-cr-* keyword from your schema and it validates the same responses it did before.

What they do change is how the document is read. Extraction knows that a currency field is money — so $1,234.56 on the page becomes 1234.56 rather than a string — that a date field should come back as an ISO date, and that an address is one contiguous postal address rather than a line of prose. Where a document is genuinely ambiguous, the value is left exactly as written: 03/04/2026 has no reading that a schema can settle, so it comes back verbatim rather than guessed into the wrong month.

Unknown field types are inert. A x-cr-kind value the API doesn’t recognize is ignored, never rejected — the field falls back to its declared base type. That is deliberate: new field types can appear without breaking a caller pinned to an older understanding, and a schema written today keeps working.

Working within the schema dialect

Annotations don’t loosen the extraction schema dialect, which is checked first:

  • select must use enum. oneOf, anyOf, allOf, const and pattern are rejected anywhere in the schema, so a choice expressed as oneOf: [{ "const": "draft" }, …] comes back as 400 invalid_schema. The enum form above is the only encoding that passes.
  • Depth and size still cap out at 5 levels and 64 KB. Annotations add keywords, not levels — every field type in the table is a scalar or an array of scalars.

A full request

One call using seven of the field types:

$curl -X POST https://api.cloudraker.com/v1/extract \
> -H "Authorization: Bearer $CLOUDRAKER_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "file": { "url": "https://example.com/invoice.pdf", "name": "invoice.pdf" },
> "schema": {
> "type": "object",
> "properties": {
> "vendor_name": { "type": ["string", "null"] },
> "vendor_address": { "type": ["string", "null"], "x-cr-kind": "address" },
> "vendor_phone": { "type": ["string", "null"], "x-cr-kind": "phone" },
> "billing_email": { "type": ["string", "null"], "format": "email" },
> "invoice_date": { "type": ["string", "null"], "format": "date" },
> "total": { "type": ["number", "null"], "x-cr-kind": "currency", "x-cr-currency": "CAD" },
> "payment_terms": {
> "type": ["string", "null"],
> "enum": ["net_15", "net_30", "net_60", null]
> },
> "notes": { "type": ["string", "null"], "x-cr-kind": "long_text" }
> }
> }
> }'

The result is ordinary JSON — the annotations shaped how the values were read, not how they’re returned:

1{
2 "vendor_name": "Northwind Supply Co.",
3 "vendor_address": "88 Rue Sainte-Catherine O, Montréal, QC H3B 1A9",
4 "vendor_phone": "+1 514 555 0142",
5 "billing_email": "[email protected]",
6 "invoice_date": "2026-03-04",
7 "total": 1234.56,
8 "payment_terms": "net_30",
9 "notes": "Delivery scheduled in two shipments."
10}

Citations work the same way as on any other field — see extract.

The same vocabulary in the app

These annotations are what the CloudRaker schema builders read and write. A schema you send to the API opens in the in-app editor with the right control per field — a currency input, a date picker, a dropdown of your enum values — and a schema you build in the app exports with the same keywords. It’s one vocabulary across the API and the product, so a saved action is editable from either side.

An unannotated schema renders as it always has: text, number, boolean, select and multi_select carry no marker at all, because they’re structurally identical to plain string, number, boolean, enum and array-of-enum.

Next steps