Before you start: you need an API key with the
contacts:read and contacts:write scopes.
See API keys.1
Define your custom fields once
Custom fields hold the data from your app that you want to segment or personalize on, such as a
plan name. Create each one with a A key that’s already taken returns
key, which is how you’ll address it in a contact’s
customFields object. The type is text, number, date, boolean or select. A
select field needs options.400. To see what exists, call
GET /contact-custom-fields. The values show on each contact in the dashboard. See
Add and edit contacts.2
Look the contact up by email
GET /contacts?search= matches a full email address exactly, ignoring case. The same search
also matches parts of first, last and display names, so confirm the match in the returned
emails array.3
Create the contact if it doesn't exist
POST /contacts creates the contact with its identities and tags in one call. It needs at
least one identity. Tags that don’t exist yet are created.data.contact. Store its id against your user record, so later updates
don’t need a search.4
Update it if it does
PATCH /contacts/{id} changes profile fields only. Identities are managed separately.5
Add another identity
Add an email address or phone number to an existing contact.Brudcast stores numbers in E.164 format.
countryCode can be a two-letter country code, such
as NG, or a dialing code, such as 234. It’s used when the number isn’t already in
international format. Use POST /contacts/{contactId}/emails with email for addresses. For
push device tokens, see Register device tokens.6
Add the contact to a list
POST /contact-lists/{id}/contacts takes up to 1,000 contact IDs. If any ID doesn’t belong to
your organization, the whole call is refused. Contacts already subscribed are left alone.POST /contacts/bulk-add-to-list does the same with listId and contactIds, but skips unknown
IDs instead of refusing the call.Put it together: a safe upsert
An email address belongs to at most one contact in an organization. APOST /contacts with an
address that’s already in use fails, so retrying a create never makes a duplicate. That makes this
pattern safe to run whenever your user changes:
- If you’ve stored the contact’s
id,PATCHit. - Otherwise, search by email and
PATCHthe match. - Otherwise,
POSTa new contact and store itsid. - If the
POSTfails because the address is taken, for example because an earlier request timed out after it succeeded, search again andPATCH.
The duplicate protection comes from email addresses. Searching doesn’t match phone numbers, so for
contacts without an email address, store the contact
id in your app and always update by id.Backfill existing users in bulk
For a first import from your app,POST /contacts/bulk creates up to 500 contacts per request,
with the same fields as POST /contacts.
201, even when every row failed. Read data.createdCount,
data.failedCount and data.errors. Each error gives the index of the failed row in your
contacts array and a message. Rows whose email address already belongs to a contact fail, so
send those through the upsert above. For a one-off spreadsheet import, the dashboard’s
CSV import can also update existing contacts.
Rules that affect a sync
Keep opt-outs in step
Two separate mechanisms keep mail away from an address, and a sync has to respect both.- The organization’s suppression list covers every kind of email: campaigns, the send API and
SMTP. Brudcast adds an address automatically after a hard bounce (any
5xxreply) or a spam complaint. The platform API has no suppression-list endpoints, so addresses your app blocks are added by hand under Contacts > Suppressions. See Suppression list. - A contact’s email identity status only affects campaigns. Campaigns address identities whose
status is
verifiedorunverified, and skipbounced,complainedandsuppressedones. The send API and SMTP don’t look at it.
suppressed. Find the identity’s
ID in the contact’s emails array.
GET /messages?status=bounced. A row with
a 5xx smtpCode is permanent, and Brudcast has already suppressed that address, so mark it
undeliverable in your app too. See Message status.
Troubleshooting
“… is not a valid phone number for the country given”
“… is not a valid phone number for the country given”
Why: the number couldn’t be turned into an international number using the
countryCode
you sent.Fix: send the number in international format, such as +2348000000001, or send the right
country code with a national number.Custom field values disappeared after an update
Custom field values disappeared after an update
Why:
PATCH /contacts/{id} replaced customFields with the object you sent.Fix: read the contact, merge your changes into its customFields, and send the full
object.Bulk create returned 201 but created nothing
Bulk create returned 201 but created nothing
Why: the endpoint reports row failures in the body, not in the status code.Fix: check
data.errors. Rows that failed because the address already exists need an
update, not a create.422 when a user has no first name
422 when a user has no first name
Why:
firstName and lastName must be at least one character long when you send them.Fix: leave out empty fields instead of sending "".Add and edit contacts
Identities, custom fields and lists on a contact in the dashboard.
Suppression list
The addresses Brudcast won’t send to, and why each one is there.
Import contacts from a CSV
A one-off spreadsheet import, which can also update existing contacts.
Create and send a campaign
Send to the contacts you’ve synced.