> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sajn.se/llms.txt
> Use this file to discover all available pages before exploring further.

# Fields that parties fill in

> Add form inputs that a party fills in while signing, next to values you fill in yourself

In this guide, you add a form to a document. Some inputs you fill in before sending, and others the party fills in while signing, such as an address or a start date.

A FORM field holds a grid of inputs, called subfields. A subfield with a `partyId` in its `fieldMeta` belongs to that party: it's empty when you send the document, and the party fills it in on the signing page. A subfield without a `partyId` is yours: you fill it in, and the party sees the value as read-only text.

## Before you begin

* Store your API key in the `SAJN_API_KEY` environment variable. To create a key, go to workspace settings in the sajn app, then **Utvecklare** (Developer) > **API-nycklar** (API keys).
* Have a `DRAFT` document with at least one `SIGNER` party, and the party's `id`. For more information, see [Create a document](/guides/documents/create-document).

## Add a form with party inputs

<Steps>
  <Step title="Create the FORM field">
    Send a `POST` request to `/api/v1/documents/DOCUMENT_ID/fields` with the FORM field in a `fields` array. Each subfield has an `id` that's unique in the form, a `row` and `column` in the grid, and its own `fieldMeta`. The following form has two values you fill in and two inputs for the party:

    <CodeGroup>
      ```bash curl theme={null}
      curl -X POST https://app.sajn.se/api/v1/documents/DOCUMENT_ID/fields \
        -H "Authorization: Bearer $SAJN_API_KEY" \
        -H "Sajn-Version: 2026-10" \
        -H "Content-Type: application/json" \
        -d '{
          "fields": [
            {
              "type": "FORM",
              "position": 1,
              "fieldMeta": {
                "type": "FORM",
                "columns": 2,
                "fields": [
                  { "id": "company", "key": "company", "row": 0, "column": 0,
                    "fieldMeta": { "type": "INPUT", "label": "Company", "value": "Example AB" } },
                  { "id": "role", "key": "role", "row": 0, "column": 1,
                    "fieldMeta": { "type": "INPUT", "label": "Role", "value": "Developer" } },
                  { "id": "address", "key": "address", "row": 1, "column": 0,
                    "fieldMeta": { "type": "INPUT", "label": "Home address", "partyId": "PARTY_ID", "required": true } },
                  { "id": "start-date", "key": "start-date", "row": 1, "column": 1,
                    "fieldMeta": { "type": "DATEPICKER", "label": "Preferred start date", "partyId": "PARTY_ID" } }
                ]
              }
            }
          ]
        }'
      ```

      ```javascript Node.js theme={null}
      const documentId = "DOCUMENT_ID";
      const partyId = "PARTY_ID";

      const response = await fetch(`https://app.sajn.se/api/v1/documents/${documentId}/fields`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.SAJN_API_KEY}`,
          "Sajn-Version": "2026-10",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          fields: [
            {
              type: "FORM",
              position: 1,
              fieldMeta: {
                type: "FORM",
                columns: 2,
                fields: [
                  { id: "company", key: "company", row: 0, column: 0,
                    fieldMeta: { type: "INPUT", label: "Company", value: "Example AB" } },
                  { id: "role", key: "role", row: 0, column: 1,
                    fieldMeta: { type: "INPUT", label: "Role", value: "Developer" } },
                  { id: "address", key: "address", row: 1, column: 0,
                    fieldMeta: { type: "INPUT", label: "Home address", partyId, required: true } },
                  { id: "start-date", key: "start-date", row: 1, column: 1,
                    fieldMeta: { type: "DATEPICKER", label: "Preferred start date", partyId } },
                ],
              },
            },
          ],
        }),
      });
      const body = await response.json();
      if (!response.ok) {
        throw new Error(`${body.code}: ${body.message} (request ${body.requestId})`);
      }
      console.log(body.data[0].id);
      ```

      ```python Python theme={null}
      import os

      import requests

      document_id = "DOCUMENT_ID"
      party_id = "PARTY_ID"

      response = requests.post(
          f"https://app.sajn.se/api/v1/documents/{document_id}/fields",
          headers={
              "Authorization": f"Bearer {os.environ['SAJN_API_KEY']}",
              "Sajn-Version": "2026-10",
          },
          json={
              "fields": [
                  {
                      "type": "FORM",
                      "position": 1,
                      "fieldMeta": {
                          "type": "FORM",
                          "columns": 2,
                          "fields": [
                              {"id": "company", "key": "company", "row": 0, "column": 0,
                               "fieldMeta": {"type": "INPUT", "label": "Company",
                                             "value": "Example AB"}},
                              {"id": "role", "key": "role", "row": 0, "column": 1,
                               "fieldMeta": {"type": "INPUT", "label": "Role",
                                             "value": "Developer"}},
                              {"id": "address", "key": "address", "row": 1, "column": 0,
                               "fieldMeta": {"type": "INPUT", "label": "Home address",
                                             "partyId": party_id, "required": True}},
                              {"id": "start-date", "key": "start-date", "row": 1, "column": 1,
                               "fieldMeta": {"type": "DATEPICKER",
                                             "label": "Preferred start date",
                                             "partyId": party_id}},
                          ],
                      },
                  },
              ],
          },
      )
      body = response.json()
      if not response.ok:
          raise RuntimeError(f"{body['code']}: {body['message']} (request {body['requestId']})")
      print(body["data"][0]["id"])
      ```
    </CodeGroup>

    Replace the following:

    * `DOCUMENT_ID`: the ID of the draft document.
    * `PARTY_ID`: the `id` of the party who fills in the inputs.

    The response has the created FORM field in `data`. `position` is the field's 0-based place among the document's content blocks.

    A subfield's `key` lets you fill it in later without knowing the field ID. Keys can contain lowercase letters, digits, hyphens, and underscores.
  </Step>

  <Step title="Change your values before sending">
    To change the values you fill in, use [Fill in values on a document](/api-reference/fill-in-values-on-a-document) with the subfield keys. It writes every value in one request:

    ```bash theme={null}
    curl -X PATCH https://app.sajn.se/api/v1/documents/DOCUMENT_ID/field-values \
      -H "Authorization: Bearer $SAJN_API_KEY" \
      -H "Sajn-Version: 2026-10" \
      -H "Content-Type: application/json" \
      -d '{ "values": [ { "key": "role", "value": "Senior developer" } ] }'
    ```

    The response lists the outcome for each key in `results`. A value that the party fills in, such as `address`, is read-only through this endpoint: its result has `success` set to `false` and an `error` with the code `INVALID_STATE`. The other values in the request are still written.
  </Step>

  <Step title="Send the document">
    Send the document as usual. On the signing page, the party sees `Company` and `Role` as text, and `Home address` and `Preferred start date` as inputs. The party can't sign until every `required` input is filled in.

    After signing, the values are on the document. Read them with [List the fillable values on a document](/api-reference/list-the-fillable-values-on-a-document). The values are in `data`, and each value the party filled in has `filledBy` set to `SIGNER` and the `partyId` of that party.
  </Step>
</Steps>

## Subfield types

The subfield type is `fieldMeta.type`, in uppercase. Every type takes `label`, `placeholder`, `description`, `partyId`, and `required`:

* `INPUT`: a single-line text input. The value is in `value`.
* `TEXT`: a text area. `rows` sets its height, from 2 to 20.
* `NUMBER`: a number input.
* `DATEPICKER`: a date picker.
* `SELECT`: a drop-down list. Set `options` to a list such as `[{ "value": "Engineering" }, { "value": "Sales" }]`, and optionally `defaultValue`.
* `RADIO`: one choice from `options`.
* `CHECKBOX`: any number of choices from `options`. The selected values are in `values`.
* `ATTACHMENT`: a file that the party uploads. `allowedTypes` takes `PDF` and `IMAGE`. After the upload, `value` is `{ filename, mimeType, size }`.

A lowercase type, such as `input`, fails with `400 VALIDATION_FAILED`.

## Give each party their own inputs

When a document has several signing parties, set each subfield's `partyId` to the party who owns it. A party can only fill in their own inputs. Another party's inputs show as empty until that party fills them in. For the signing order, see [Multi-party signing](/guides/documents/multi-party-signing).

## Change who fills in a subfield

To move a subfield to another party, or back to yourself, update the FORM field that holds it. A `PATCH` request replaces the field's whole `fieldMeta`, so start from the stored one:

1. To find the FORM field by the subfield's key, call `GET /api/v1/documents/DOCUMENT_ID/fields?key=address`. The field is in `data`.
2. In its `fieldMeta.fields`, change the subfield's `partyId`. To fill the subfield in yourself, set `partyId` to `null` and set `value`.
3. Send the whole `fieldMeta` to [Update a document field](/api-reference/update-a-document-field):

```bash theme={null}
curl -X PATCH https://app.sajn.se/api/v1/documents/DOCUMENT_ID/fields/FIELD_ID \
  -H "Authorization: Bearer $SAJN_API_KEY" \
  -H "Sajn-Version: 2026-10" \
  -H "Content-Type: application/json" \
  -d '{
    "fieldMeta": {
      "type": "FORM",
      "columns": 2,
      "fields": [
        { "id": "company", "key": "company", "row": 0, "column": 0,
          "fieldMeta": { "type": "INPUT", "label": "Company", "value": "Example AB" } },
        { "id": "role", "key": "role", "row": 0, "column": 1,
          "fieldMeta": { "type": "INPUT", "label": "Role", "value": "Developer" } },
        { "id": "address", "key": "address", "row": 1, "column": 0,
          "fieldMeta": { "type": "INPUT", "label": "Home address", "partyId": null, "value": "Storgatan 1, Stockholm" } },
        { "id": "start-date", "key": "start-date", "row": 1, "column": 1,
          "fieldMeta": { "type": "DATEPICKER", "label": "Preferred start date", "partyId": "PARTY_ID" } }
      ]
    }
  }'
```

Replace `FIELD_ID` with the FORM field's `id`. The response is the updated FORM field. A field is addressed by its ID only; to change a value without changing who fills it in, use [Fill in values on a document](/api-reference/fill-in-values-on-a-document) instead.

## Handle errors

* `400 VALIDATION_FAILED`: a subfield is invalid, for example without `row`, with an unknown or lowercase `type`, or with `signerId` instead of `partyId`. Read `issues` for the path.
* `409 INVALID_STATE`: the document isn't a `DRAFT`. Fields can change only before sending.
* `404 NOT_FOUND`: no field on the document has the ID.

For the error shape and every code, see [Errors](/api-fundamentals/errors).

## Next steps

<CardGroup cols={2}>
  <Card title="Place fields on a PDF" icon="signature" href="/guides/fields/pdf-field-placement">
    Put inputs and signature boxes on an uploaded PDF.
  </Card>

  <Card title="Templates and forms" icon="file-lines" href="/guides/templates/templates-and-forms">
    Reuse a form across documents.
  </Card>

  <Card title="Fields" icon="lightbulb" href="/concepts/fields">
    Learn how the field model works.
  </Card>

  <Card title="Create document fields" icon="code" href="/api-reference/create-document-fields">
    See every field type in the API reference.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.