The contract shape

When Emboss processes a form it produces a contract: the structured list of every field it detected. The contract is the source of truth for what's on the form: its labels, types, and positions. You can inspect it directly.

Getting the contract

Once a form has finished detection, fetch its contract from GET /forms/{id}/contract:

curl https://api.getemboss.ai/forms/6c47f7f5-f921-4698-910f-95dd7d81310b/contract \
  -H "Authorization: Bearer sk_..."
  • 200: detection is complete. The body is { "id": "<form id>", "contract": { ... } }: the contract sits under contract, so read the fields from contract.fields.
  • 409: the form isn't ready yet (contract not available (status: …)). Poll again shortly.
  • 404: no such form, or it belongs to another owner.

What's in it

The answer wraps the contract with the form's id. The contract itself has schema_version, page_count, field_count, a form object (its title), and a fields array. Each field has an integer id, a machine name, the detected label, a widget type, the expected data_type, whether it's required, the page it's on, a rect (its position), and a value that is always null: the contract describes the form, and a fill never writes into it.

{
  "id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "contract": {
    "schema_version": "1.0",
    "page_count": 1,
    "field_count": 16,
    "form": { "title": "Form W-9" },
    "fields": [
      {
        "id": 1,
        "name": "business_name",
        "label": "Business name",
        "type": "text",
        "data_type": "organization",
        "required": true,
        "page": 0,
        "rect": { "x": 72, "y": 540, "width": 320, "height": 18 },
        "value": null
      },
      {
        "id": 7,
        "label": "Exempt payee code applies",
        "type": "checkbox",
        "data_type": "boolean",
        "required": false,
        "page": 0,
        "rect": { "x": 88, "y": 470, "width": 12, "height": 12 },
        "value": null
      },
      {
        "id": 8,
        "name": "phone_number",
        "label": "Phone Number",
        "type": "comb",
        "page": 0,
        "rect": { "x": 100.0, "y": 600.0, "width": 172.8, "height": 24.0 },
        "parts": [
          { "rect": { "x": 100.0, "y": 600.0, "width": 43.2, "height": 24.0 }, "cells": 3 },
          { "rect": { "x": 157.6, "y": 600.0, "width": 43.2, "height": 24.0 }, "cells": 3 },
          { "rect": { "x": 215.2, "y": 600.0, "width": 57.6, "height": 24.0 }, "cells": 4 }
        ],
        "max_len": 10,
        "charset": "digits",
        "value": null
      },
      {
        "id": 9,
        "name": "tax_classification",
        "label": "Federal tax classification",
        "type": "radio",
        "data_type": "other",
        "required": true,
        "page": 0,
        "options": [
          { "value": "opt_0", "label": "Individual/sole proprietor", "rect": { "x": 88, "y": 450, "width": 12, "height": 12 } },
          { "value": "opt_1", "label": "C corporation", "rect": { "x": 188, "y": 450, "width": 12, "height": 12 } }
        ],
        "value": null
      }
    ]
  }
}

A comb is a row of single-character boxes. Its parts list each run of boxes with its cell count; a fill writes one character per box, stripping separators when charset is digits, and a read returns the joined value.

Fields carry a few more keys too: description, instructions, format_hint, section, group, related_fields, option_label, office_use, and confidence, but the ones above are what you'll reach for most. A radio field lists its choices in options, each with the value you send to choose it (sometimes a generated opt_0, opt_1), a label and a rect.

data_type is one of person_name, organization, street_address, city_state_zip, phone, fax, email, date, currency, number, parcel_id, free_text, boolean, signature or other.

Pages count from 0 here; reading a filled form back counts them from 1.

Why inspect it

  • Verify detection before you commit to a fill: confirm the fields and labels are what you expect.
  • Map your own data to each field's integer id: that same id is the field_id you pass to PUT /sessions/{sid}/fields for a precise, deterministic fill (see Sessions).
  • Audit which fields are checkboxes, combs, signatures, or free text.

Because the contract spells out every detected field, you can inspect exactly what Emboss found before you fill, and confirm the fields are what you expect.