curl --request POST \
--url https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"records": [
{
"id": "obj_183ed5cc-3182-45de-84d1-d520f2604810",
"name": "Project Alpha",
"people": [
{
"id": "per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2"
}
],
"customFieldValues": {
"Status": "Won"
}
}
]
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
records: [
{
id: 'obj_183ed5cc-3182-45de-84d1-d520f2604810',
name: 'Project Alpha',
people: [{id: 'per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2'}],
customFieldValues: {Status: 'Won'}
}
]
})
};
fetch('https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update"
payload = { "records": [
{
"id": "obj_183ed5cc-3182-45de-84d1-d520f2604810",
"name": "Project Alpha",
"people": [{ "id": "per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2" }],
"customFieldValues": { "Status": "Won" }
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)require 'uri'
require 'net/http'
url = URI("https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"records\": [\n {\n \"id\": \"obj_183ed5cc-3182-45de-84d1-d520f2604810\",\n \"name\": \"Project Alpha\",\n \"people\": [\n {\n \"id\": \"per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2\"\n }\n ],\n \"customFieldValues\": {\n \"Status\": \"Won\"\n }\n }\n ]\n}"
response = http.request(request)
puts response.read_bodypackage main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update"
payload := strings.NewReader("{\n \"records\": [\n {\n \"id\": \"obj_183ed5cc-3182-45de-84d1-d520f2604810\",\n \"name\": \"Project Alpha\",\n \"people\": [\n {\n \"id\": \"per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2\"\n }\n ],\n \"customFieldValues\": {\n \"Status\": \"Won\"\n }\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'records' => [
[
'id' => 'obj_183ed5cc-3182-45de-84d1-d520f2604810',
'name' => 'Project Alpha',
'people' => [
[
'id' => 'per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2'
]
],
'customFieldValues' => [
'Status' => 'Won'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}{
"data": {
"results": [
{
"status": "succeeded",
"data": {
"id": "obj_183ed5cc-3182-45de-84d1-d520f2604810",
"name": "Project Alpha",
"companies": [
{
"id": "com_92346499-30bf-4278-ae8e-4aa3ae2ace2c",
"name": "Tech Corp"
}
],
"people": [
{
"id": "per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2",
"fullName": "John Doe"
}
],
"createdAt": "2021-01-01T00:00:00.000Z",
"createdBy": {
"id": "usr_bc984b3f-0386-434d-82d7-a91eb6badd71",
"fullName": "John Doe",
"email": "john.doe@example.com"
},
"customFieldValues": {
"Status": "Active",
"Deal value": "42000",
"Close date": "2021-01-01",
"Assignee": [
{
"id": "usr_c3606e3b-0a92-4849-90e5-88a8d3f388d6",
"fullName": "Jane Doe",
"email": "jane@example.com"
}
]
}
}
},
{
"status": "failed",
"error": {
"code": "NOT_FOUND",
"message": "Not found.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#not-found"
}
}
]
}
}{
"error": {
"code": "INVALID_REQUEST",
"message": "The request was invalid.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#bad-request",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "No valid API key provided.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#unauthorized",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "FORBIDDEN",
"message": "The API key doesn’t have permissions to perform the request.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#forbidden",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "The requested resource was not found.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#not-found",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "IDEMPOTENCY_REQUEST_IN_PROGRESS",
"message": "A request with the same Idempotency-Key is still being processed. Retry once it has completed.",
"documentationUrl": "https://developer.folk.app/api-reference/idempotency#errors",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "UNPROCESSABLE_ENTITY",
"message": "Invalid query parameters",
"documentationUrl": "https://developer.folk.app/api-reference/errors#unprocessable-entity",
"details": {
"issues": [
{
"code": "too_small",
"minimum": 1,
"type": "number",
"inclusive": true,
"exact": false,
"message": "Number must be greater than or equal to 1",
"path": [
"limit"
]
}
]
},
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "TOO_MANY_REQUESTS",
"message": "You have exceeded your rate limit.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#rate-limiting",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z",
"details": {
"policy": "burst",
"limit": 20,
"remaining": 0,
"windowSeconds": 2,
"retryAfter": "2025-10-01T12:00:02.000Z",
"policies": [
{
"policy": "default",
"limit": 600,
"remaining": 412,
"windowSeconds": 60,
"retryAfter": "2025-10-01T12:01:00.000Z"
},
{
"policy": "burst",
"limit": 20,
"remaining": 0,
"windowSeconds": 2,
"retryAfter": "2025-10-01T12:00:02.000Z"
}
]
}
}
}{
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "An internal server error occurred.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#internal-server-error",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "The service is currently unavailable.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#service-unavailable",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}Update deals in batch
Update up to 100 existing deals of one type in a group, each with the fields PATCH /v1/groups/{groupId}/{objectType}/{objectId} accepts. Each record is updated on its own: one that fails does not prevent the others from being updated.
people and companies replace the people and companies of the deal: you must provide the entire list, not just the ones you want to add. Leave them out to keep them unchanged. They are given by ID, and an unknown one, or one not in the group, is ignored, as in PATCH /v1/groups/{groupId}/{objectType}/{objectId}.
A record whose ID designates an object of another type, or of another group, fails as not found.
The records of one deal are merged into one update, in request order: the last value given for a field wins, and customFieldValues are merged field by field, 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 deal fails with that error. Each of those records gets its own result, with the deal as finally updated.
An object type that does not exist in the group fails the whole request with a 404, whose message lists the object types of the group.
curl --request POST \
--url https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"records": [
{
"id": "obj_183ed5cc-3182-45de-84d1-d520f2604810",
"name": "Project Alpha",
"people": [
{
"id": "per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2"
}
],
"customFieldValues": {
"Status": "Won"
}
}
]
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
records: [
{
id: 'obj_183ed5cc-3182-45de-84d1-d520f2604810',
name: 'Project Alpha',
people: [{id: 'per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2'}],
customFieldValues: {Status: 'Won'}
}
]
})
};
fetch('https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update"
payload = { "records": [
{
"id": "obj_183ed5cc-3182-45de-84d1-d520f2604810",
"name": "Project Alpha",
"people": [{ "id": "per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2" }],
"customFieldValues": { "Status": "Won" }
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)require 'uri'
require 'net/http'
url = URI("https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"records\": [\n {\n \"id\": \"obj_183ed5cc-3182-45de-84d1-d520f2604810\",\n \"name\": \"Project Alpha\",\n \"people\": [\n {\n \"id\": \"per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2\"\n }\n ],\n \"customFieldValues\": {\n \"Status\": \"Won\"\n }\n }\n ]\n}"
response = http.request(request)
puts response.read_bodypackage main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update"
payload := strings.NewReader("{\n \"records\": [\n {\n \"id\": \"obj_183ed5cc-3182-45de-84d1-d520f2604810\",\n \"name\": \"Project Alpha\",\n \"people\": [\n {\n \"id\": \"per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2\"\n }\n ],\n \"customFieldValues\": {\n \"Status\": \"Won\"\n }\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.folk.app/v1/groups/{groupId}/{objectType}/batch/update",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'records' => [
[
'id' => 'obj_183ed5cc-3182-45de-84d1-d520f2604810',
'name' => 'Project Alpha',
'people' => [
[
'id' => 'per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2'
]
],
'customFieldValues' => [
'Status' => 'Won'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}{
"data": {
"results": [
{
"status": "succeeded",
"data": {
"id": "obj_183ed5cc-3182-45de-84d1-d520f2604810",
"name": "Project Alpha",
"companies": [
{
"id": "com_92346499-30bf-4278-ae8e-4aa3ae2ace2c",
"name": "Tech Corp"
}
],
"people": [
{
"id": "per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2",
"fullName": "John Doe"
}
],
"createdAt": "2021-01-01T00:00:00.000Z",
"createdBy": {
"id": "usr_bc984b3f-0386-434d-82d7-a91eb6badd71",
"fullName": "John Doe",
"email": "john.doe@example.com"
},
"customFieldValues": {
"Status": "Active",
"Deal value": "42000",
"Close date": "2021-01-01",
"Assignee": [
{
"id": "usr_c3606e3b-0a92-4849-90e5-88a8d3f388d6",
"fullName": "Jane Doe",
"email": "jane@example.com"
}
]
}
}
},
{
"status": "failed",
"error": {
"code": "NOT_FOUND",
"message": "Not found.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#not-found"
}
}
]
}
}{
"error": {
"code": "INVALID_REQUEST",
"message": "The request was invalid.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#bad-request",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "No valid API key provided.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#unauthorized",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "FORBIDDEN",
"message": "The API key doesn’t have permissions to perform the request.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#forbidden",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "The requested resource was not found.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#not-found",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "IDEMPOTENCY_REQUEST_IN_PROGRESS",
"message": "A request with the same Idempotency-Key is still being processed. Retry once it has completed.",
"documentationUrl": "https://developer.folk.app/api-reference/idempotency#errors",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "UNPROCESSABLE_ENTITY",
"message": "Invalid query parameters",
"documentationUrl": "https://developer.folk.app/api-reference/errors#unprocessable-entity",
"details": {
"issues": [
{
"code": "too_small",
"minimum": 1,
"type": "number",
"inclusive": true,
"exact": false,
"message": "Number must be greater than or equal to 1",
"path": [
"limit"
]
}
]
},
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "TOO_MANY_REQUESTS",
"message": "You have exceeded your rate limit.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#rate-limiting",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z",
"details": {
"policy": "burst",
"limit": 20,
"remaining": 0,
"windowSeconds": 2,
"retryAfter": "2025-10-01T12:00:02.000Z",
"policies": [
{
"policy": "default",
"limit": 600,
"remaining": 412,
"windowSeconds": 60,
"retryAfter": "2025-10-01T12:01:00.000Z"
},
{
"policy": "burst",
"limit": 20,
"remaining": 0,
"windowSeconds": 2,
"retryAfter": "2025-10-01T12:00:02.000Z"
}
]
}
}
}{
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "An internal server error occurred.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#internal-server-error",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "The service is currently unavailable.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#service-unavailable",
"requestId": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2025-10-01T12:00:00Z"
}
}id. Each record takes the same fields as update a deal and is updated on its own: a record that fails, for instance because of an unknown custom field, does not prevent the others from being updated. See batch requests for the 100-record limit and how to read the response. Each deal comes back in full, as in the response of update a deal.
A batch targets one object type in one group, given by the path. An object type that does not exist in the group fails the whole request with a 404, whose message lists the object types of the group. A record whose id designates an object of another type, or of another group, fails as not found. If the API key cannot update deals in the group, every record fails.
people and companies replace the people and companies of the deal: you
must provide the entire list, not just the ones you want to add. Leave them
out to keep them unchanged.customFieldValues are merged field by field, 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 deal fails with that error. Each of those records gets its own result, with the deal as finally updated. This is not always the same as sending the records one after the other: a record with an invalid custom field value fails every record of its deal, including the earlier ones, which sent on their own would have been applied before it.
A record that succeeded but whose people, companies or custom field values could not all be set carries a warnings list explaining what was not applied.Authorizations
API key for authentication
Headers
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.
255"8e03978e-40d5-43e8-bc93-6894a57f9324"
Path Parameters
The ID of the group the deals belong to. Can be retrieved from the List groups endpoint.
40The name of a deal custom field that can be retrieved from the List group custom fields endpoint.
500Body
100Show child attributes
Show child attributes
Response
The outcome of each record, with each updated deal.
Show child attributes
Show child attributes
{
"results": [
{
"status": "succeeded",
"data": {
"id": "obj_183ed5cc-3182-45de-84d1-d520f2604810",
"name": "Project Alpha",
"companies": [
{
"id": "com_92346499-30bf-4278-ae8e-4aa3ae2ace2c",
"name": "Tech Corp"
}
],
"people": [
{
"id": "per_5fa60242-0756-4e31-8cca-30c2c5ff1ac2",
"fullName": "John Doe"
}
],
"createdAt": "2021-01-01T00:00:00.000Z",
"createdBy": {
"id": "usr_bc984b3f-0386-434d-82d7-a91eb6badd71",
"fullName": "John Doe",
"email": "john.doe@example.com"
},
"customFieldValues": {
"Status": "Active",
"Deal value": "42000",
"Close date": "2021-01-01",
"Assignee": [
{
"id": "usr_c3606e3b-0a92-4849-90e5-88a8d3f388d6",
"fullName": "Jane Doe",
"email": "jane@example.com"
}
]
}
}
},
{
"status": "failed",
"error": {
"code": "NOT_FOUND",
"message": "Not found.",
"documentationUrl": "https://developer.folk.app/api-reference/errors#not-found"
}
}
]
}
["This field is deprecated"]