Skip to Content
GuidesFields

Fields

Fields define where signers need to sign, initial, or fill in information on a document.

Field Types

TypeDescription
signatureFull signature (drawn or typed)
initialsInitials only
dateAuto-filled signing date
textFree-form text input
checkboxBoolean checkbox
dropdownSingle choice from a fixed option list (options)

Field Properties

PropertyTypeDescription
idstringUnique identifier
signerIdstringWhich signer fills this field
fieldTypeenumType of field
pageNumbernumberPDF page (1-indexed)
xPositionnumberX coordinate from left edge (points)
yPositionnumberY coordinate from top edge (points)
widthnumberField width (points)
heightnumberField height (points)
requiredbooleanWhether field must be filled
labelstringPrompt shown to the signer (e.g. “Your full name”)
valuestringFilled value (null until signed)
optionsstring[]Allowed values for dropdown fields
acroFieldNamestringEmbedded PDF form field this field fills (see Fillable PDFs)
maxLengthnumberMaximum characters accepted at fill time
validationPatternstringRegex the value must match (see Fillable PDFs)
validationMessagestringSigner-facing error when the pattern does not match
groupKeystringMembers sharing a key are mutually exclusive (choose-one)
groupRequiredbooleanRequire at least one member of the group to be selected
requiredWhenFieldIdstringConditional requirement: the field is required only while the referenced field is checked/filled (see Conditionally Required Fields)
requiredWhenValuestringNarrows the condition to one exact value of the referenced field
sharedFillbooleanAny signer able to act may fill or correct it until its owner signs (see Shared-Fill Fields)

Adding Fields

// Add a signature field const signatureField = await korala.fields.create(documentId, { signerId: signer.id, fieldType: 'signature', pageNumber: 1, xPosition: 100, // 100 points from left yPosition: 500, // 500 points from top width: 200, height: 50, }); // Add initials field const initialsField = await korala.fields.create(documentId, { signerId: signer.id, fieldType: 'initials', pageNumber: 1, xPosition: 400, yPosition: 700, width: 80, height: 40, }); // Add date field (auto-fills when signed) const dateField = await korala.fields.create(documentId, { signerId: signer.id, fieldType: 'date', pageNumber: 1, xPosition: 300, yPosition: 500, width: 150, height: 30, });

Collecting Information from Signers

Signers can fill in fields themselves. The signer completes any field created without a value in the signing UI, on the hosted signing page and inside the embedded <KoralaSigner> iframe alike. Use this to collect data your application doesn’t have, such as phone numbers or consent checkboxes, without adding those questions to your own forms.

What the signer sees for each field type:

Field TypeSigner interaction
textInline text input on the document
checkboxClick to check
dateAuto-fills the signing date on click
signatureOpens the signature pad (draw or type)
initialsOpens the signature pad for initials

Date formats

When a signer clicks a date field, the filled value follows the format the document requires, resolved in this order:

  1. The field’s dateFormat property — e.g. dateFormat: 'MM-DD-YYYY' fills 08-20-2026. Accepted formats combine D/DD, M/MM, and YY/YYYY tokens with a consistent -, /, or . separator; invalid formats are rejected at field creation. Only valid on date fields — for typed text input, use validationPattern instead.
  2. A format token in the field’s label — e.g. label: 'Date (MM-DD-YYYY)'. Handy when the label already prints the required format.
  3. The field’s validationPattern — common formats are tested against the regex and the first match is used (e.g. ^\d{4}-\d{2}-\d{2}$ fills 2026-08-20).
  4. Otherwise the signer’s browser-locale format.

Set dateFormat explicitly when the document mandates a format; template fields carry it onto every generated document.

Set a label so the field shows a meaningful prompt instead of the generic “Enter text”:

// The signer types their phone number into the document await korala.fields.create(documentId, { signerId: signer.id, fieldType: 'text', label: 'Phone number', pageNumber: 1, xPosition: 100, yPosition: 400, width: 200, height: 30, }); // The signer checks a consent box await korala.fields.create(documentId, { signerId: signer.id, fieldType: 'checkbox', label: 'I agree to the terms', pageNumber: 1, xPosition: 100, yPosition: 450, width: 30, height: 30, });

Fields are required by default, so the signer cannot complete signing until they fill each required field. Korala stamps the filled values into the final PDF and returns them via the API once the signer has signed:

const fields = await korala.fields.list(documentId); for (const field of fields) { if (field.value) { console.log(`${field.label ?? field.fieldType}: ${field.value}`); } }

If you’re embedding the signing UI, the React SDK emits an onFieldFilled event each time the signer fills a field, so your app can track progress in real time.

Prefilled values are read-only by default. A text, date, dropdown, or checkbox field that already has a value (for example from template merge variables, bulk generation, or a signing-packet lock) renders in the signing UI as a muted value with a “set by the sender” hint, and the signer cannot change it. To prefill a value the signer may correct, set editable: true on the template field; see Editable Defaults. Prefill non-editable values only for data you’re certain of.

Each field reports who wrote its current value in filledBy: sender for a non-editable prefill or a packet lock, signer for anything the signer entered (including bulk signing on their behalf), and null while nobody has filled it, which includes an editable default the signer has not confirmed. The signing UI uses it to tell the sender’s values apart from the signer’s own entries.

Shared-Fill Fields

Some forms are prepared by one party and confirmed by another: HR types the employment details, the employee checks them and signs. Set sharedFill: true on a field and any signer whose turn the signing order allows may fill or correct it — until the field’s owner signs, which freezes it for everyone.

await korala.fields.update(documentId, fieldId, { sharedFill: true, });

The field still belongs to one signer. It counts toward their required fields, their signing locks the final value, and the completed PDF carries whatever stood when they signed — so the owner always has the last word on a prepared value. The audit trail records who actually wrote each value.

Rules to know:

  • sharedFill applies to text, date, checkbox, and dropdown fields. Signature and initials fields refuse it: a signature can only come from its owner.
  • Order the owner after the preparer. A shared field owned by signer 1 freezes as soon as they sign, before signer 2’s turn ever starts.
  • A required shared field is satisfied by a prepared value alone; keep the owner last in the signing order if they must see it before it counts.

In the signing UI, another signer’s shared field renders with a dashed border and names its owner. Template fields accept the same flag and carry it onto every generated document.

Conditionally Required Fields

Some fields are mandatory only when another answer makes them so. On the IRS W-9, the LLC tax-classification code (C, S, or P) must be filled only when the LLC classification box is checked. Express that by pointing the dependent field at its controller:

const llcBox = await korala.fields.create(documentId, { signerId: signer.id, fieldType: 'checkbox', label: 'LLC', pageNumber: 1, xPosition: 73, yPosition: 193, width: 8, height: 8, required: false, }); await korala.fields.create(documentId, { signerId: signer.id, fieldType: 'text', label: 'LLC tax classification (C, S, or P)', pageNumber: 1, xPosition: 418, yPosition: 192, width: 29, height: 11, requiredWhenFieldId: llcBox.id, });

While the controller is off, the field stays optional. Once the signer checks the box, the field turns required: it joins the progress counter, gets required styling, and Korala refuses completion until it is filled, with the error "LLC tax classification (C, S, or P)" is required when "LLC" is selected. Unchecking releases it again.

Rules to know:

  • The controller must be a field on the same document belonging to the same signer. A checkbox controller counts when checked; any other type counts once filled.
  • Set requiredWhenValue to trigger only on one exact value — e.g. a dropdown’s "Other" choice requiring a “please specify” text field.
  • Korala stores a conditional field as individually optional, forcing its required flag off at creation and rejecting required: true on later updates while the condition stands. The condition alone decides.
  • Choose-one group members cannot carry a condition (the group’s groupRequired covers them), though a group member — like the LLC box, part of the W-9’s classification group — can be a controller.
  • Clear a condition with requiredWhenFieldId: null on update. Clearing or re-pointing it also drops any requiredWhenValue narrowing, since a value chosen for one controller means nothing against another.
  • Reassigning either field to a different signer clears the condition: the sign gate evaluates within one signer’s fields, so a cross-signer link could never be enforced and Korala refuses to store one that looks live.
  • Template fields accept the same properties, and generated documents carry the condition with references remapped for you.

Coordinate System

PDF coordinates use points (1 point = 1/72 inch):

  • Origin is at the top-left corner of the page
  • xPosition increases going right
  • yPosition increases going down
  • A standard US Letter page is 612 x 792 points
(0,0) ────────────────────────────► x (612) │ ┌─────────────────┐ │ │ PDF Content │ │ │ │ │ │ ┌─────────┐ │ │ │ │ Field │ │ │ │ │(100,500)│ │ │ │ └─────────┘ │ │ │ │ │ └─────────────────┘ y (792)

Use the document viewer to find coordinates, or calculate positions from page dimensions.

Fillable PDFs (AcroForm)

Many pre-created documents, like the IRS W-9, ship as fillable PDFs with embedded form fields. Korala reads those fields and writes values back through them: detection proposes each field at its exact position, linked fields fill natively (SSN digits land one per comb box, checkboxes render the form’s own checkmark), and the completed document is flattened so it can no longer be edited.

See Fillable PDFs for the full flow, including the GET /documents/{id}/form-fields discovery endpoint and radio-group handling.

Field TypeWidthHeight
signature20050
initials8040
date15030
text20030
checkbox3030

How Content Fills the Box

width and height set the field’s bounds. They do not set the size of what lands inside it, so a box in the right place can still put the ink in the wrong one.

Signatures and initials. Korala scales the image to fit inside the box, preserves its aspect ratio, then centres it on both axes — the same “contain” rule the signer preview uses, so a signature never stretches. Whichever dimension runs out first sets the scale, and the other gains padding.

Signature images are usually much wider than they are tall, so width is normally the constraint. A 600 x 21 px signature in a 200 x 24 pt box scales by 200 / 600, rendering about 7pt tall and leaving ~8pt of padding above and below:

┌──────────────────────────────────┐ ← 24pt box │ │ │ ~~~~~~~~~~~~~~~~~~~~~~~ │ ← ~7pt of ink, centred │ │ └──────────────────────────────────┘

To make the signature render larger, narrow the box rather than raising its height.

Text, date and dropdown. Values render left-aligned with 4pt of left padding, centred against the box height, at min(12, height * 0.6) points (a field imported from a fillable PDF keeps the point size, color and alignment the form declares). A single-line value is never wrapped or shrunk to fit, so a value wider than the box overflows it — size the box for your longest expected value. A multiline field instead lays text out from the top of the box, word-wrapped to its width, and drops lines that don’t fit the height.

Checkbox. A checked box draws an X centred in the box, sized to min(width, height) * 0.6. An unchecked field draws nothing. (A checkbox linked to an embedded form field renders the form’s own checkmark instead — see Fillable PDFs.)

The signing page previews filled values with these same rules — size, face, alignment and wrapping — so what a signer sees while filling is what the completed document shows.

Listing Fields

const fields = await korala.fields.list(documentId); for (const field of fields) { console.log(`${field.fieldType} on page ${field.pageNumber}`); console.log(` Position: (${field.xPosition}, ${field.yPosition})`); console.log(` Assigned to: ${field.signerId}`); if (field.value) { console.log(` Value: ${field.value}`); } }

Removing Fields

await korala.fields.delete(documentId, fieldId);

You can remove fields only while the document is in draft status.

Multiple Signers Example

Placing fields for multiple signers on the same document:

// Create document and add signers const alice = await korala.signers.create(documentId, { email: '[email protected]', name: 'Alice (Seller)', signingOrder: 1, }); const bob = await korala.signers.create(documentId, { email: '[email protected]', name: 'Bob (Buyer)', signingOrder: 2, }); // Alice's fields (left side) await korala.fields.create(documentId, { signerId: alice.id, fieldType: 'signature', pageNumber: 2, xPosition: 50, yPosition: 650, width: 200, height: 50, }); await korala.fields.create(documentId, { signerId: alice.id, fieldType: 'date', pageNumber: 2, xPosition: 50, yPosition: 710, width: 100, height: 25, }); // Bob's fields (right side) await korala.fields.create(documentId, { signerId: bob.id, fieldType: 'signature', pageNumber: 2, xPosition: 350, yPosition: 650, width: 200, height: 50, }); await korala.fields.create(documentId, { signerId: bob.id, fieldType: 'date', pageNumber: 2, xPosition: 350, yPosition: 710, width: 100, height: 25, });

Response Format

{ "id": "fld_abc123", "documentId": "doc_xyz789", "signerId": "sig_def456", "fieldType": "signature", "pageNumber": 1, "xPosition": 100, "yPosition": 500, "width": 200, "height": 50, "required": true, "value": null, "signatureImageUrl": null, "filledAt": null, "filledBy": null, "createdAt": "2024-01-14T09:00:00Z", "updatedAt": "2024-01-14T09:00:00Z" }
Last updated on