---
title: "Update people in batch"
method: POST
path: "/v1/people/batch/update"
tags: ["People"]
---

# Update people in batch

`POST /v1/people/batch/update`

## Request

- Base URL: `https://api.folk.app`
- URL: `https://api.folk.app/v1/people/batch/update`
- Auth: HTTP bearer

Update up to 100 existing people in the workspace, each with the fields `PATCH /v1/people/{personId}` accepts. Each record is updated on its own: one that fails does not prevent the others from being updated.

Fields with a list of values (`groups`, `companies`, `addresses`, `emails`, `phones`, `urls`) will **replace the old values**. This means that you must provide the entire list of values for that field, not just the values you want to add.

**`groups` replaces the groups of the person, and removing a group deletes data.** A group you can access that is missing from `groups` is removed from the person, together with the person's custom field values in that group. This is the opposite of `POST /v1/people/batch/create`, where `groups` only adds: the same payload adds groups when it creates a person and removes groups when it updates one. Leave `groups` out to keep the person's groups unchanged. Each result lists the groups it removed in `removedGroups`.

The records of one person, by its ID or by the ID of a person merged into it, are merged into one update, in request order: the last value given for a field wins, and `customFieldValues` are merged group by group, the last value given for a custom field winning. The merged update is validated as a whole: if it is invalid, every record of that person fails with that error. Each of those records gets its own result, with the person as finally updated.

## Headers

- `Idempotency-Key` string: A unique key, such as a UUID, that makes retrying this request safe: a retry with the same key and body returns the original response without running the operation again. Keys are kept for 24 hours after the request completes.

## Request body

- object
  - `records` object[], required
    - `id` string, required: The ID of the person to update.
    - `firstName` string: The first name of the person.
    - `lastName` string: The last name of the person.
    - `fullName` string: The full name of the person.
    - `description` string: A short description of the person.
    - `birthday` union: The birthday of the person, in ISO format. Deleted with null or empty string.
      - string, date
      - ''
    - `gender` 'Male' | 'Female' | 'Unknown' | 'Other', nullable: The gender of the person. Authorized values are "Female", "Male", "Unknown", "Other" or null to delete it.
    - `jobTitle` string: The job title of the person.
    - `groups` object[]: The groups the person must be in after the update, replacing its current groups: a group you can access that is not listed is removed, with the custom field values of the person in it. Leave it out to keep the current groups. You must provide group ids.
      - `id` string, required
    - `companies` union[]: The companies associated with the person. You can either provide a name or an id. If you provide a name, the company will be created if it does not already exist. The first company in the list will be the person's primary company.
      - union
        - object
          - `name` string, required
        - object
          - `id` string, required
    - `addresses` string[]: A list of addresses associated with the person. The first address in the list will be the person's primary address.
    - `emails` string[]: A list of email addresses associated with the person. The first email address in the list will be the person's primary email address.
    - `phones` string[]: A list of phone numbers associated with the person. The first phone number in the list will be the person's primary phone number.
    - `urls` string[]: A list of URLs associated with the person. The first URL in the list will be the person's primary URL.
    - `customFieldValues` object: The custom field values associated with the person, grouped by group ids. The format is the following: ```json { "<groupId>": { "<customFieldName>": "<customFieldValue>" } } ``` The group ids passed must also be provided in the `groups` field, otherwise a validation error will be thrown. The format of the custom field value depends on the type of the custom field: - `textField`: string, eg: `"Foo"` - `numericField`: number or numeric string, eg: `42` or `"42"` - `dateField`: ISO 8601 string (YYYY-MM-DD), eg: `"2021-01-01"` - `singleSelect`: string (option label), eg: `"Active"`. Use the exact option labels of the custom field (case-sensitive): an unknown label creates a new option. - `multipleSelect`: array of strings (option labels), eg: `["B2B", "B2C"]`. Use the exact option labels of the custom field (case-sensitive): an unknown label creates a new option. - `contactField`: array of objects with `id` property, eg: `[{"id": "per_20228901-ce2b-418c-a267-671823107d8c"}]` - `userField`: array of objects with either `id` (workspace user id) or `email` (workspace user email) property, eg: `[{"id": "usr_a23373bb-5296-4c59-b2e8-8f121707d562"}, {"email": "jane@example.com"}]` - `objectField`: array of objects with `id` property, eg: `[{"id": "obj_2f62707c-52c0-421a-a11f-68e1ce9610f4"}]` Passing a `null` value or an empty array will unset the custom field value.

## Response `200`

The outcome of each record, with each updated person.

- object
  - `data` object, required
    - `results` union[], required: One result per record, in the order of `records`: the first result is the outcome of the first record.
      - union
        - object
          - `status` 'succeeded', required
          - `data` Person, required: A person in the workspace.
            - `id` string, required
            - `firstName` string, required: The first name of the person.
            - `lastName` string, required: The last name of the person.
            - `fullName` string, required: The full name of the person.
            - `description` string, required: A short description of the person.
            - `birthday` string, date, nullable, required: The birthday of the person, in ISO format. Deleted with null or empty string.
            - `gender` 'Male' | 'Female' | 'Unknown' | 'Other', nullable, required: The gender of the person. Authorized values are "Female", "Male", "Unknown", "Other" or null to delete it.
            - `jobTitle` string, required: The job title of the person.
            - `createdAt` string, nullable, required: The date and time the person was created, in ISO format.
            - `createdBy` User, required: A user in the workspace.
              - …
            - `groups` object[], required: The groups associated with the person.
              - …
            - `companies` object[], required: The companies associated with the person. The first company in the list is the person's primary company.
              - …
            - `addresses` string[], required
            - `emails` string[], required
            - `phones` string[], required
            - `urls` string[], required
            - `customFieldValues` object, required
            - `interactionMetadata` InteractionMetadata, required: Metadata about interactions with the user and workspace.
              - …
            - `strongestConnection` object: For each group the person is in, the workspace member with the strongest connection to the person. If the person has no strongest connection, this will be an empty object. Only the groups for which the person has a strongest connection will be included.
          - `removedGroups` object[], required: The groups this update removed the person from, along with its custom field values in them.
            - `id` string, required
          - `warnings` string[]: What could not be applied to this record although it succeeded, such as a group it could not be added to.
        - object
          - `status` 'failed', required
          - `error` BatchRecordError, required: Why this record did not succeed.
            - `code` string, required
            - `message` string, required
            - `documentationUrl` string, uri, required
            - `details` object
  - `deprecations` string[]

## Other responses

- `400`: The request was unacceptable, often due to missing an invalid parameter.
- `401`: No valid API key provided.
- `403`: The API key doesn’t have permissions to perform the request.
- `404`: The requested resource doesn’t exist.
- `409`: A request with the same `Idempotency-Key` is still being processed, or the resource is in a state that does not allow the operation.
- `422`: The request was unacceptable, often due to missing or invalid parameters.
- `429`: Too many requests hit the API too quickly. We recommend an exponential backoff of your requests.
- `500`: Something went wrong on our end.
- `503`: The server is overloaded or down for maintenance.

## Changes

- **2026-11-03** `c6818f3ba60d`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/folk/apis/folk-external-api/changes/v1/people/batch/update/post.md)

---

[API](https://skmtc.dev/folk/apis/folk-external-api.md) - [All operations](https://skmtc.dev/folk/apis/folk-external-api/llms.txt) - [OpenAPI document](https://skmtc.dev/folk/apis/folk-external-api/revisions/c6818f3ba60d?raw)
