Create or update contacts in bulk
POST
/v1/contacts/batch
const result = await bird.contacts.batch({
contacts: [{ email: "jane@acme.com", first_name: "Jane" }],
});
for (const item of result.data) {
console.log(item.entry.email, item.status);
}result = client.contacts.batch(contacts=[{"email": "jane@acme.com", "first_name": "Jane"}])
for item in result.data:
print(item.entry.email, item.status)result, err := client.Contacts.Batch(context.Background(), bird.ContactBatchParams{
Contacts: []bird.ContactCreateRequest{
{Email: bird.Ptr(openapi_types.Email("a@x.com"))},
},
})
if err != nil {
log.Fatal(err)
}
for _, item := range result.Data {
email := ""
if item.Entry.Email != nil {
email = *item.Entry.Email
}
fmt.Println(email, item.Status)
}$result = $bird->contacts->batch(
(new ContactUpsertRequest())->setContacts([
(new ContactCreateRequest())->setEmail('jane@acme.com')->setFirstName('Jane'),
]),
);
printf("%d contacts upserted\n", count($result->getData() ?? []));bird contacts batch --body-file - <<'JSON'
{
"audience_ids": [
"adn_01krdgeqcxet5s7t44vh8rt9mg"
],
"contacts": [
{
"email": "alice@acme.com",
"first_name": "Alice",
"last_name": "Anderson"
},
{
"email": "bob@acme.com",
"first_name": "Bob",
"last_name": "Baker"
}
]
}
JSONcurl -X POST "https://us1.platform.bird.com/v1/contacts/batch" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"contacts": [
{
"email": "alice@acme.com",
"first_name": "Alice",
"last_name": "Anderson"
},
{
"email": "bob@acme.com",
"first_name": "Bob",
"last_name": "Baker"
}
],
"audience_ids": [
"adn_01krdgeqcxet5s7t44vh8rt9mg"
]
}'Creates or updates up to 1,000 contacts in one request. Each entry is matched automatically against every identifier it supplies: its email address (trimmed and lowercased before matching), its phone number (normalized to international form), and your own external_id. An entry that matches no existing contact creates one; an entry whose identifiers all point at one contact updates it with the fields it supplies, and omitted fields keep their stored values, so a contact's email address can change under a stable external_id without creating a second record. An entry whose identifiers belong to more than one contact fails with an error naming each matched contact, since Bird never merges contacts or picks between them. Supplying match_on overrides the automatic matching: every entry is matched by that one field only, and must carry it. Optionally adds every contact in the request to up to 10 audiences.
Each entry succeeds or fails on its own: the response lists one result per contact in submission order (created, updated, or failed with the reason), and a failed entry does not abort the rest. If the request itself is invalid, for example when an entry in audience_ids does not exist, the whole request fails with a validation error and no contacts are written.
Cuerpo de la solicitud
contacts
array of object
obligatorio
Contacts to create or update, matched automatically against every identifier an entry supplies. Existing contacts are updated with the fields each entry supplies; omitted fields keep their stored values, so an entry can set fields but never clear them. Unmatched entries create contacts.
Mostrar parámetros secundarios
contacts.email
string
The contact's email address. Trimmed and lowercased before it is stored and checked for uniqueness. Unique within the workspace. Supply an email address, a phone number, or both.
contacts.phone_number
string
The contact's phone number in E.164 format, including the leading + and country code. Spaces and punctuation are accepted and stripped; the number is stored in its canonical form, which may differ from what you send, and is unique within the workspace. An empty string is treated as if the field were omitted. Supply an email address, a phone number, or both.
contacts.first_name
string
The contact's first name.
contacts.last_name
string
The contact's last name.
contacts.external_id
string
Your own identifier for this contact, such as a user ID in your system. Unique within the workspace when set.
contacts.data
object
Custom property values for this contact. Each key must be a property created via the contact properties API, and each value must be a string, number, boolean, or RFC 3339 datetime matching the property's declared type (strings up to 500 characters); a null value is ignored. Unregistered or archived keys are rejected with a validation error. Total size is capped at 2 KB serialized.
audience_ids
array of string
Audiences every contact in this request is added to. Contacts that are already members are left in place. Every listed audience must exist, or the whole request fails with a validation error and nothing is written.
match_on
string
Optional. Forces every entry to be matched to an existing contact by this one field, which every entry must then carry. When omitted, each entry is matched automatically against every identifier it supplies: no match creates a contact, one match updates it, and an entry whose identifiers belong to more than one contact fails with an error naming each.
Possible values: email, phone_number, external_id
data_mode
string
How a supplied data object is applied to an existing contact. merge (the default) merges the supplied keys onto the contact's stored custom values, and a key with a null value deletes that one key. replace overwrites the whole stored data map with the supplied one. In both modes a contact that omits data keeps its stored values unchanged, so an import that touches one attribute never wipes the others.
Possible values: merge, replace
Carga de respuesta
data
array of object
obligatorio
One entry per contact in the request, in submission order.
Mostrar atributos secundarios
data.entry
object
obligatorio
The identifiers a batch entry supplied, in the normalized form they were matched with, null where the entry carried none. An echo of the request row for correlation, never the contact's current state.
Mostrar atributos secundarios
data.entry.email
nullable string
obligatorio
Email address this entry carried, trimmed and lowercased. Null when the entry carried none.
data.entry.phone_number
nullable string
obligatorio
Phone number this entry carried, in its normalized international form. Null when the entry carried none. A row rejected for an invalid phone echoes the value as sent, trimmed, since no normalized form exists.
data.entry.external_id
nullable string
obligatorio
Your own identifier for this entry, when the entry supplied one.
data.matched_on
nullable string
obligatorio
Which identifier matched this entry to an existing contact. Null when the entry created a new contact.
Possible values: email, phone_number, external_id, null
data.status
string
obligatorio
What happened to this contact. created means a new contact was created for the address; updated means an existing contact with the address was updated; failed means the entry was rejected and error explains why. A failed entry does not affect the other entries in the request.
Possible values: created, updated, failed
data.contact_id
string
ID of the created or updated contact. Absent when the entry failed.
data.error
object
Why this entry failed. Absent for successful entries.
Mostrar atributos secundarios
data.error.type
string
obligatorio
Machine-readable error category for this entry, such as validation_error or conflict_error, in the same vocabulary as the top-level error type. New categories may be added over time, so treat unrecognized values as a generic failure.
data.error.code
string
obligatorio
The specific error code for this entry, from the same catalog as the top-level error code: the discriminator within a category. E04058 (the entry matched two different contacts, a human must decide) and E04055 (the phone belongs to another contact, retry with different data) are both conflict_error; the code tells a sync which one it hit.
data.error.message
string
obligatorio
Human-readable explanation of why this entry failed.