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

# Pre-Fill and Update

> Pre-fill and update business verification forms through the iDenfy KYB API: company details, custom fields, beneficiaries, documents and questionnaire answers.

<Note>
  **Requirements**

  * **API** key pair
  * Session creation via API **enabled** (done by iDenfy staff)
  * **Finances** for the KYB flow you use
</Note>

Pre-filling lets you send the data you already hold — company name, registration number, directors, documents, questionnaire answers — into a Business verification form before the client opens it. The client sees those values in the Web UI and completes only what is missing. The same endpoints let you correct a form later, including after it has been submitted.

## KYB API Pre-Fill Flow

| Step | Request | Auth |
| - | - | - |
| 1. [Create a token](#step-1-create-a-token) | `POST /kyb/tokens/` | API key pair |
| 2. [Read the flow](#step-2-read-the-flow) | `GET /kyb/info/` | `tokenString` |
| 3. [Create the form with company data](#step-3-create-the-form) | `POST /kyb/forms/` | `tokenString` |
| 4. [Add beneficiaries](#step-4-add-beneficiaries) | `POST /kyb/forms/{companyId}/beneficiaries/` | Either |
| 5. [Upload documents](#step-5-upload-documents) | `POST /kyb/forms/{companyId}/documents/` | Either |
| 6. [Answer the questionnaire](#step-6-answer-the-questionnaire) | `PUT /kyb/forms/{companyId}/questionnaires/{id}/answers/` | Either |
| 7. [Hand the form to the client](#step-7-hand-the-form-to-the-client) | Web UI link | — |

Steps 4–6 are optional — run the ones you have data for.

## Authentication

KYB form endpoints accept two credentials, but not every endpoint accepts both.

* **`tokenString`** — sent as `Authorization: Bearer <tokenString>`. Acts as the client filling in their own form.
* **API key pair** — HTTP basic auth with your API key and secret. Acts as you, the partner.

| Endpoint | `tokenString` | API key pair |
| - | - | - |
| `POST /kyb/tokens/` | No | **Yes** |
| `GET /kyb/info/` | **Yes** | No |
| `POST /kyb/forms/` (create) | **Yes** | No |
| `POST /kyb/forms/{companyId}/submit/` | **Yes** | No |
| `GET`, `PUT`, `PATCH /kyb/forms/{companyId}/` | Yes | Yes |
| Beneficiaries, documents, questionnaires | Yes | Yes |

Calling a `tokenString`-only endpoint with the API key pair returns **401**.

***

## Step 1: Create a Token

Create a session as described in [Create KYB Session](/kyb/generate-token).

```json theme={"system"}
{
  "tokenType": "FORM",
  "clientId": "client-1042",
  "lifetime": 86400,
  "flow": "3f6c1e0a-8b2d-4f5e-9a71-2c4d5e6f7a8b"
}
```

* If you omit `flow`, iDenfy uses your account's default KYB flow.
* iDenfy refuses token creation if your account lacks finances for the flow.
* Set `lifetime` long enough for the client to finish. The maximum is **2,592,000** seconds (30 days); the default is one hour.

Keep `tokenString` and `companyId` from the response — every following step uses them. The response also echoes the session settings (`expiration`, `isValid`, `clientId`, `externalRef`, `flow`, `tags` and others); see `kybTokensCreate` in the API Reference.

***

## Step 2: Read the Flow

Call `GET /kyb/info/` with the `tokenString`. The `flow` object describes what the form expects:

| Field | What it tells you |
| - | - |
| `flow.fields` | Built-in company fields, each with `required` |
| `flow.fieldsCustom` | Custom fields, each with its `key`, `type`, `required` and — for select fields — `choices` |
| `flow.documents` | Document types the flow accepts |
| `flow.beneficiaries` | Beneficiary types the flow includes and whether each is required |

If `flow` is `null`, every field and section is present in the form.

Read custom field keys and choice keys from this response at run time rather than hard-coding them. They are defined in your dashboard workflow, so a copied value goes stale the moment someone edits the workflow or you switch flows.

***

## Step 3: Create the Form

`POST /kyb/forms/` creates the form and is where pre-filling starts. Authorize it with the `tokenString`.

```json theme={"system"}
{
  "company": {
    "companyName": "Acme Ltd",
    "country": "GB",
    "registrationNumber": "12345678",
    "type": "Ltd",
    "email": "info@acme.com",
    "phone": "+441234567890",
    "website": "https://acme.com",
    "postalAddress": "1 Example Street, London EC1A 1BB",
    "city": "London",
    "postcode": "EC1A 1BB",
    "additionalInfo": {
      "industry": { "value": "fintech" }
    }
  }
}
```

The same request can also carry `beneficiaries` and `documents` arrays, so steps 4 and 5 can be folded into this call.

**Rules for this request:**

* **Once per token.** A second call returns *"KYB form is already created."* Change the data afterwards with an [update](#updating-a-form).
* **The flow's required fields apply.** Each missing required field comes back as its own *"This field is required."* error. You cannot leave a required field for the client — see [Partial Pre-Fill](#partial-pre-fill).
* **Fields outside the flow are silently dropped**, not rejected. A field missing from the saved form usually means the flow does not include it.

<Warning>
  The form does not exist until this call succeeds. Calling `PATCH /kyb/forms/{companyId}/` straight after token creation returns **404**, even though the token response already contains a `companyId`.
</Warning>

### Company Fields

`companyName` and `country` are always required. The rest are optional unless your flow marks them required.

| Field | Type | Notes |
| - | - | - |
| `companyName` | string | Legal name. Max 200 characters |
| `country` | string | ISO 3166-1 alpha-2 |
| `registrationNumber` | string | Max 100 characters |
| `region` | string | State or province code, max 2 characters |
| `type` | string | Legal entity type, e.g. `LLC`, `GmbH`, `Ltd`. Max 100 characters |
| `email` | string | Max 254 characters |
| `phone` | string | [E.164](https://wikipedia.org/wiki/E.164) format, e.g. `+37061234567` |
| `website` | string | Full URL including `https://`. Max 200 characters |
| `brandNames` | array | Trading names. Up to 10, each max 100 characters |
| `activityCode` | string | Max 8 characters |
| `tin` | string | Taxpayer identification number. Max 32 characters |
| `operatingAddress` | string | Max 255 characters |
| `postalAddress` | string | Registration address. Max 255 characters |
| `street` | string | Max 100 characters |
| `city` | string | Max 100 characters |
| `postcode` | string | Max 20 characters |
| `additionalInfo` | object | Custom fields — see below |

### Custom Fields

Custom fields from your workflow go in `company.additionalInfo`, keyed by the field's `key` from step 2. Each entry is an object with a single `value`:

```json theme={"system"}
"additionalInfo": {
  "<field key>": { "value": <value> }
}
```

| `type` | `value` | Example |
| - | - | - |
| `TEXT` | string, max 100 characters | `"Retail payments"` |
| `INTEGER` | integer | `25` |
| `DATE` | `YYYY-MM-DD` | `"2019-04-01"` |
| `CHECKBOX` | boolean | `true` |
| `COUNTRY` | ISO 3166-1 alpha-2 | `"LT"` |
| `COUNTRY_MULTI` | array of country codes | `["LT", "LV"]` |
| `SELECT` | a choice `key` | `"fintech"` |
| `SELECT_MULTI` | array of choice `key`s | `["cards", "wallets"]` |

<Warning>
  Select fields take the choice's **`key`**, not the label the client sees. The API rejects the label (for example `"Financial Technology"` instead of `"fintech"`). Look the key up in `flow.fieldsCustom[].field.choices` from step 2.
</Warning>

***

## Step 4: Add Beneficiaries

Add each person or company with `POST /kyb/forms/{companyId}/beneficiaries/`, one request per beneficiary, or send them all in the `beneficiaries` array of step 3.

```json theme={"system"}
{
  "beneficiaryTypes": ["CEO", "SHAREHOLDER"],
  "positions": ["director"],
  "ownershipPercentage": 62.5,
  "formFiller": true,
  "info": {
    "infoType": "INDIVIDUAL",
    "name": "Jane",
    "surname": "Smith",
    "email": "jane@acme.com",
    "dateOfBirth": "1985-02-14",
    "nationality": "GB"
  }
}
```

| Field | Notes |
| - | - |
| `beneficiaryTypes` | One or more of `CEO`, `REPRESENTATIVE`, `SHAREHOLDER`, `UBO`, `ABO` — one person can hold several roles |
| `info` | **Required.** The person or company — see below |
| `positions` | Array of up to 3 strings, e.g. `director`, `shareholder`. Max 50 characters each |
| `ownershipPercentage` | `0`–`100`, decimals allowed. Relevant for `SHAREHOLDER`, `UBO` and `ABO` |
| `formFiller` | `true` if this person will complete the form |
| `parent` | ID of a company beneficiary, for nested ownership structures |

**`info` for a person** — `infoType: "INDIVIDUAL"`. `name` and `surname` are required. Optional:

| Field | Notes |
| - | - |
| `email`, `phone` | Phone in E.164 format |
| `dateOfBirth` | `YYYY-MM-DD` |
| `nationality`, `citizenship`, `countryOfBirth` | ISO 3166-1 alpha-2 |
| `country` | ID issuing country, ISO 3166-1 alpha-2 |
| `documentNumber`, `personalNumber` | Max 50 characters, ASCII only |
| `residentialAddress`, `address` | Max 255 characters |
| `street`, `city` | Max 100 characters |
| `postcode` | Max 20 characters |
| `countryOfResidence`, `taxResidence` | ISO 3166-1 alpha-2 |
| `tin` | Max **20** characters — shorter than the company `tin` |
| `selfDeclaredPep` | Boolean |
| `additionalInfo` | Custom beneficiary fields, same format as [company custom fields](#custom-fields) |

**`info` for a company** — `infoType: "COMPANY"`. `companyName` and `country` are required; the remaining fields match the [company fields](#company-fields).

<Tip>
  If the person has already passed identity verification with you, set `scanRef` in `info` to link it instead of asking them to verify again. This only works with the **API key pair**. With the `tokenString`, the API silently ignores it. See [KYC Integration](/kyb/kyc-integration#reusing-an-identity-verification-across-companies).
</Tip>

A beneficiary's type cannot be changed after creation. Delete it and add a new one instead.

***

## Step 5: Upload Documents

Upload company documents with `POST /kyb/forms/{companyId}/documents/`, or include them in the `documents` array of step 3. Each document needs a `type` and a base64-encoded `file`.

```json theme={"system"}
{
  "type": "INCORPORATION_CERT",
  "filename": "certificate.pdf",
  "file": "JVBERi0xLjcKJ..."
}
```

The flow determines which document types you can upload. Check `flow.documents` from step 2. Upload limits are listed in [Collect Information](/kyb/collect-information#upload-constraints).

***

## Step 6: Answer the Questionnaire

If the flow has a questionnaire, iDenfy attaches it to the form when you create the token:

* **With a flow** — the flow's questionnaire.
* **Without a flow** — the questionnaire named in the token's `questionnaire` field, or your account's default.
* **None** — when the token sets `questionnaireRequired: false` or uses a flow router.

You can only save answers once the form exists (step 3). You cannot send them with the token.

### Get the Questionnaire

`GET /kyb/forms/{companyId}/questionnaires/` returns each questionnaire's `id`, `key`, `title` and `sections`. Each section has a `key` and `questions`; each question has a `key`, `type`, `required`, `choices` and an optional `condition`. An empty list means no questionnaire is attached.

### Save the Answers

`PUT /kyb/forms/{companyId}/questionnaires/{id}/answers/`, using the questionnaire `id` from the previous call:

```json theme={"system"}
{
  "sections": {
    "<sectionKey>": {
      "<questionKey>": { "value": "..." }
    }
  }
}
```

Use the section and question keys **exactly** as returned. These are keys you defined, so they are not converted to camelCase.

| Question `type` | `value` |
| - | - |
| `CHECKBOX` | `true` / `false` |
| `TEXT` | String, max 100 characters |
| `TEXT_AREA` | String, max 20,000 characters |
| `INTEGER`, `FLOAT` | Number |
| `DATE` | `YYYY-MM-DD`. `TIME` and `DATETIME` are also supported |
| `EMAIL` | Email address |
| `URL` | Max 200 characters |
| `TEL` | International format, e.g. `+37061234567` |
| `COUNTRY` | ISO 3166-1 alpha-2, e.g. `"LT"` |
| `COUNTRY_MULTI` | Array of country codes |
| `SELECT`, `RADIO` | A choice `key` |
| `SELECT_MULTI` | Array of choice `key`s |
| `LIST` | Array of short strings, max 20 items |
| `FILE` | Base64 image or PDF, max 10 MB |
| `FILE_MULTI` | Array of up to 5 base64 files |

**Validation:**

* Questions are optional unless marked `required`.
* Required questions inside a section or question whose `condition` is not met are skipped.
* If any required question is missing, the whole request is rejected — partial answers can fail.

### Check What Is Saved

* `GET /kyb/forms/{companyId}/questionnaires/{id}/answers/` — the raw answers, or **204** if none are saved yet.
* `GET /kyb/forms/{companyId}/questionnaires/answers/detail/` — a readable version with titles and choice labels.

<Note>
  The form cannot be submitted without saved answers — submission fails with *"To submit please answer a questionnaire."*

  KYC questionnaires cannot be pre-filled: their answers can only be saved from the client's own verification session.
</Note>

***

## Step 7: Hand the Form to the Client

Do **not** submit the form. Send the client to the Web UI with the same `tokenString`:

```
https://kyb.ui.idenfy.com/?authToken=<tokenString>
```

The token response contains no link, so build it yourself. If a custom KYB URL is configured for your account, use that instead, with the `tokenString` in place of its `{{token_string}}` placeholder. The client sees every pre-filled value — including questionnaire answers and uploaded files — completes the rest and submits. You receive a [webhook](/kyb/webhooks) once it is submitted.

To complete the whole form through the API instead, see [Collect Information](/kyb/collect-information).

***

## Updating a Form

Once the form exists, change company data with `PUT` or `PATCH /kyb/forms/{companyId}/`. Beneficiaries, documents and questionnaire answers each keep their own endpoints.

| | Create — `POST /kyb/forms/` | Update — `PUT` / `PATCH /kyb/forms/{companyId}/` |
| - | - | - |
| **When** | Once per token | Only after the form exists — **404** before |
| **Auth** | `tokenString` only | `tokenString` or API key pair |
| **Covers** | Company, plus `beneficiaries` and `documents` | The `company` block only |
| **Statuses** | New form starts as `PENDING` | `tokenString`: `PENDING` only. API key pair: any status except `PROCESSING` |

* **`PUT`** replaces the whole `company` block — include every required field.
* **`PATCH`** changes only the fields you send. Everything else stays as it is.

### Validation Depends on the Credential

* **`tokenString`** — the flow's rules apply, exactly as on create: required fields must be present and fields outside the flow are dropped. After a [Request Update](/guides/dashboard/kyb/request-update-kyb), only the requested fields can change; everything else is read-only.
* **API key pair** — the flow's required and allowed rules are **not** applied to standard company fields. Only the basic checks remain: `companyName` and `country` cannot be empty, plus format and length limits. Custom fields in `additionalInfo` are still checked against the flow.

<Warning>
  After submission only the API key pair can update a form, and the flow no longer protects standard company fields. Double-check what you send — a `PUT` that omits a field the flow requires is accepted.
</Warning>

Updates made with the API key pair are logged in the company's change history as a partner edit (*"Edited company data: …"*). Changes made with the `tokenString` — by the client, or by you using the token — are not logged as partner edits.

### Updating Questionnaire Answers

* **A `PUT` replaces all saved answers.** Any question you leave out is cleared, so send the full set every time — `GET` the current answers, change what you need, and `PUT` everything back.
* **Files:** to keep an existing file, send back the file link from the `GET` response. Any file not included in the `PUT` is deleted.
* **To clear all answers**, `DELETE` the same answers path. The form then cannot be submitted until answers are saved again.
* **Statuses:** with the `tokenString`, only while the form is `PENDING`. With the API key pair, at any status except `PROCESSING` — including after submission (`NEED_TO_REVIEW`, `NEED_TO_PROCESS`, `COMPLETED`).

### Beneficiaries and Documents

Use the update and delete operations on their own endpoints. See [Collect Information](/kyb/collect-information#beneficiaries) for the full list.

***

## Limitations

### Pre-Filled Values Stay Editable

The client can change any value you pre-fill, including questionnaire answers. There is no API option to lock a field during the first submission.

If certain data must not change:

1. Fill **every** field through the API, setting the flow fields you cannot supply to optional.
2. Submit the form with `POST /kyb/forms/{companyId}/submit/` (`tokenString` only).
3. In the dashboard, use [Request Update](/guides/dashboard/kyb/request-update-kyb) and select only the sections the client may edit. Everything not selected is read-only for the client.

<Note>
  Request Update is a dashboard action. You cannot trigger it through the API, so step 3 is manual for every company.
</Note>

### Partial Pre-Fill

Form creation applies the flow's required fields, so when you hold only some of the data you have two options:

* **Make those fields optional in the flow** — you can then pre-fill any subset, at the risk that the client skips fields you need.
* **Keep them required and do not pre-fill** — the client enters all the information themselves, and nothing is missed.


## Related topics

- [Update questionnaire answers](/api-reference/kyb-questionnaires/update-questionnaire-answers.md)
- [Update KYB form info](/api-reference/kyb-forms/update-kyb-form-info.md)
- [Partially update KYB form info](/api-reference/kyb-forms/partially-update-kyb-form-info.md)
- [Collect Information](/kyb/collect-information.md)
- [Create new KYB form](/api-reference/kyb-forms/create-new-kyb-form.md)


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