curl --request POST \
--url https://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"records": [
{
"clientDedupKey": "org-123",
"fields": {
"dashboard_region": "us"
}
}
]
}
'import requests
url = "https://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch"
payload = { "records": [
{
"clientDedupKey": "org-123",
"fields": { "dashboard_region": "us" }
}
] }
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({records: [{clientDedupKey: 'org-123', fields: {dashboard_region: 'us'}}]})
};
fetch('https://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch', 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://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch",
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' => [
[
'clientDedupKey' => 'org-123',
'fields' => [
'dashboard_region' => 'us'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <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://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch"
payload := strings.NewReader("{\n \"records\": [\n {\n \"clientDedupKey\": \"org-123\",\n \"fields\": {\n \"dashboard_region\": \"us\"\n }\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<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://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"records\": [\n {\n \"clientDedupKey\": \"org-123\",\n \"fields\": {\n \"dashboard_region\": \"us\"\n }\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"records\": [\n {\n \"clientDedupKey\": \"org-123\",\n \"fields\": {\n \"dashboard_region\": \"us\"\n }\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"processed": 1,
"succeeded": 1,
"failed": 0,
"results": [
{
"success": true,
"id": "1cfa4f66-5db2-4ce5-b4b0-b9c801f3ad7c",
"clientDedupKey": "org-123",
"operation": "CREATE"
}
]
}
}{
"error": {
"code": "invalid_email",
"message": "invalid email format: not-an-email"
}
}{
"error": {
"code": "invalid_email",
"message": "invalid email format: not-an-email"
}
}{
"error": {
"code": "invalid_email",
"message": "invalid email format: not-an-email"
}
}{
"error": {
"code": "invalid_email",
"message": "invalid email format: not-an-email"
}
}{
"error": {
"code": "invalid_email",
"message": "invalid email format: not-an-email"
}
}Batch Upsert Custom Object Records
Create or update up to 200 records of one custom object. Create the custom object in Conversion and define its fields first. Each record requires a stable clientDedupKey from your source system. Requires edit-records access to the custom object.
HTTP 200 includes one result per input, in order, with processed, succeeded, and failed counts. Repeated keys in a batch are processed sequentially by the same ingestion path used for warehouse syncs. Correct missing keys and invalid fields before retrying. Invalid requests, access denials, or service failures return a non-200 response.
Relationship values use the target record’s clientDedupKey, with an email fallback for contacts. Missing targets remain pending, so record success does not mean every relationship has resolved. This endpoint does not create companies, opportunities, or other relationship targets.
curl --request POST \
--url https://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"records": [
{
"clientDedupKey": "org-123",
"fields": {
"dashboard_region": "us"
}
}
]
}
'import requests
url = "https://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch"
payload = { "records": [
{
"clientDedupKey": "org-123",
"fields": { "dashboard_region": "us" }
}
] }
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({records: [{clientDedupKey: 'org-123', fields: {dashboard_region: 'us'}}]})
};
fetch('https://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch', 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://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch",
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' => [
[
'clientDedupKey' => 'org-123',
'fields' => [
'dashboard_region' => 'us'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <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://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch"
payload := strings.NewReader("{\n \"records\": [\n {\n \"clientDedupKey\": \"org-123\",\n \"fields\": {\n \"dashboard_region\": \"us\"\n }\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<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://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"records\": [\n {\n \"clientDedupKey\": \"org-123\",\n \"fields\": {\n \"dashboard_region\": \"us\"\n }\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://pub-api.conversion.ai/api/v2/custom-objects/{customObjectId}/records/batch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"records\": [\n {\n \"clientDedupKey\": \"org-123\",\n \"fields\": {\n \"dashboard_region\": \"us\"\n }\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"processed": 1,
"succeeded": 1,
"failed": 0,
"results": [
{
"success": true,
"id": "1cfa4f66-5db2-4ce5-b4b0-b9c801f3ad7c",
"clientDedupKey": "org-123",
"operation": "CREATE"
}
]
}
}{
"error": {
"code": "invalid_email",
"message": "invalid email format: not-an-email"
}
}{
"error": {
"code": "invalid_email",
"message": "invalid email format: not-an-email"
}
}{
"error": {
"code": "invalid_email",
"message": "invalid email format: not-an-email"
}
}{
"error": {
"code": "invalid_email",
"message": "invalid email format: not-an-email"
}
}{
"error": {
"code": "invalid_email",
"message": "invalid email format: not-an-email"
}
}Authorizations
Your Conversion API key. Found in Settings > Integrations in the dashboard. Format: sk_live_<key_id>_<secret>.
Path Parameters
The ID of the existing custom object created in Conversion.
Body
1 - 200 elementsShow child attributes
Show child attributes
Response
Per-record write results.
Show child attributes
Show child attributes
Was this page helpful?