Extract

Field types

Optional annotations that tell extraction what a field means, such as a currency, a phone number, or a date, without a change to the response shape.
View as Markdown

A schema field says what type a value has. A field type says what the value is. {"type": "number"} could be a quantity or an amount of money. {"type": "string"} could be a paragraph, a phone number, or a mailing address. An annotation helps extraction read the field. It also makes the in-app editors render the field correctly.

Annotations are optional. A schema with none behaves exactly as before. Every annotated schema is still plain, valid JSON Schema. It uses standard format where one exists, and x-cr-* vendor keywords for the rest. A validator that does not know 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 names the field type. x-cr-currency is a per-field setting for currency. Six field types need neither: date, datetime, email, and url use standard JSON Schema format, and select / multi_select use enum.

Combine annotations with the rest of your schema as usual. Nullability is the common case:

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 as before.

Annotations change how extraction reads the document. Extraction knows that a currency field is money. So $1,234.56 on the page becomes 1234.56, not a string. A date field comes back as an ISO date. An address is one contiguous postal address, not a line of prose. Where a document is ambiguous, extraction keeps the value exactly as written. 03/04/2026 has no reading that a schema can settle, so it comes back verbatim, not guessed into the wrong month.

Unknown field types are inert. The API ignores an x-cr-kind value it does not recognize. It never rejects one. The field falls back to its declared base type. This is deliberate. New field types can appear without a break for callers pinned to an older understanding. A schema you write today keeps working.

Working within the schema dialect

Annotations do not loosen the extraction schema dialect. The API checks the dialect first:

  • select must use enum. The API rejects oneOf, anyOf, allOf, const, and pattern anywhere in the schema. 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 caps still apply: 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 uses 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 extraction read the values, not how the API returns them:

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

The CloudRaker schema builders read and write these annotations. A schema you send to the API opens in the in-app editor with the correct control per field: a currency input, a date picker, or a dropdown of your enum values. A schema you build in the app exports with the same keywords. One vocabulary covers the API and the product. You can edit a saved config from either side.

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

Next steps