curl --request POST \
--url https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk \
--header 'Content-Type: application/json' \
--header 'x-access-token: <api-key>' \
--data '
{
"operations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"data": {}
}
]
}
'import requests
url = "https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk"
payload = { "operations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"data": {}
}
] }
headers = {
"x-access-token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-access-token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({operations: [{id: '3c90c3cc-0d44-4b50-8888-8dd25736052a', data: {}}]})
};
fetch('https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk",
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([
'operations' => [
[
'id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'data' => [
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-access-token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk"
payload := strings.NewReader("{\n \"operations\": [\n {\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"data\": {}\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-access-token", "<api-key>")
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))
}HttpResponse<String> response = Unirest.post("https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk")
.header("x-access-token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"operations\": [\n {\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"data\": {}\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-access-token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"operations\": [\n {\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"data\": {}\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"batch_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"results": [
{
"index": 123,
"action": "<string>",
"status": "success",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"error": {
"code": "TYPE_MISMATCH",
"message": "Field 'product_type' value 'Banana' is not a valid option. Valid options: [\"1\", \"Banana, Chocolate\", \"Blue, Green, Violet\", \"10\"]",
"valid_options": [
"1",
"Banana, Chocolate",
"Blue, Green, Violet",
"10"
]
},
"error_code": "<string>"
}
],
"summary": {
"total": 123,
"succeeded": 123,
"failed": 123
}
}Bulk contact operations
Create, update, or delete multiple contacts in a single request (max
100 operations). Requires the write:contacts scope. Fields an event
marks Required in Record Settings are not enforced on create, as
with contacts/create.
Send the { action, id, data } envelope every other bulk endpoint
uses. This endpoint previously read the contact fields off the
operation itself and rejected the documented envelope with
email is required on every action; that is fixed, and the flat form
below is still accepted for existing integrations.
Operations are applied in request order, one transaction each. An
operation that fails leaves nothing behind — no partially written
contact, no dangling event association — and the operations around it
still apply. results comes back in request order, so
results[i] always describes operations[i].
data accepts the same fields as POST /contacts/create, including
custom_fields and translated_fields. A create whose email already
exists in the organization links that contact to the event instead of
duplicating it, and reports status: "associated".
Deprecated: flat operations. An operation with no action key is
treated as a create, with the operation object itself as its data:
{ "email": "[email protected]", "first_name": "Ada" } behaves like
{ "action": "create", "data": { "email": "[email protected]", "first_name": "Ada" } }.
This shape is supported for existing callers only and will not gain
new capabilities. Send the envelope.
curl --request POST \
--url https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk \
--header 'Content-Type: application/json' \
--header 'x-access-token: <api-key>' \
--data '
{
"operations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"data": {}
}
]
}
'import requests
url = "https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk"
payload = { "operations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"data": {}
}
] }
headers = {
"x-access-token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-access-token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({operations: [{id: '3c90c3cc-0d44-4b50-8888-8dd25736052a', data: {}}]})
};
fetch('https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk",
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([
'operations' => [
[
'id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'data' => [
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-access-token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk"
payload := strings.NewReader("{\n \"operations\": [\n {\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"data\": {}\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-access-token", "<api-key>")
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))
}HttpResponse<String> response = Unirest.post("https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk")
.header("x-access-token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"operations\": [\n {\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"data\": {}\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://public-api.sessionboard.com/v1/event/{eventId}/contacts/bulk")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-access-token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"operations\": [\n {\n \"id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"data\": {}\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"batch_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"results": [
{
"index": 123,
"action": "<string>",
"status": "success",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"error": {
"code": "TYPE_MISMATCH",
"message": "Field 'product_type' value 'Banana' is not a valid option. Valid options: [\"1\", \"Banana, Chocolate\", \"Blue, Green, Violet\", \"10\"]",
"valid_options": [
"1",
"Banana, Chocolate",
"Blue, Green, Violet",
"10"
]
},
"error_code": "<string>"
}
],
"summary": {
"total": 123,
"succeeded": 123,
"failed": 123
}
}Authorizations
Organization API token. Generate from Organization Settings → API Tokens.
Path Parameters
The event ID.
Body
Request body for bulk create/update/delete operations.
Operations are applied in request order, each in its own transaction,
and results[i] describes operations[i]. A failed operation is
rolled back whole and does not stop the ones after it.
Array of operations to execute (max 100).
100Show child attributes
Show child attributes
Response
Bulk operation completed
Response body for bulk operations, including per-item results.
Unique identifier for this bulk batch.
Per-operation results in the same order as the request.
Show child attributes
Show child attributes
Aggregate counts for the batch. This page previously named the object stats; every bulk endpoint has always returned it as summary.
Show child attributes
Show child attributes

