Skip to main content

Contacts

The /contacts endpoint allows you to view and modify your Dripcel contacts.

Get a single contact

GET /contacts/:cell

Get a single contact by their cell number.

  • 🔐 Permissions: ["contact.read.pii"]

Request

URL Parameters

FieldTypeRequiredDescription
cellstringThe MSISDN of the contact you want to view.

Response

Success

200
{
ok: true,
data: Contact
}

Error

400
{
ok: false;
error: "Invalid cell number";
}
404
{
ok: false;
error: "Contact not found";
}

Search for contacts

POST /contacts/search

Run a search query on your contacts.

  • 🔐 Permissions: ["contact.read.pii"]
  • 💵 Paid endpoint: 10 credits per request

Request

Body

tip

The find, projection, and options fields all use (a subset of) MongoDB query syntax. You can find more information in the MongoDB documentation.

type ContactSearchBody = {
/** The search query. All fields are optional, but atleast one filter needs to be passed */
find?: {
/** The cell number of the contact */
cell?: string[];
/** The tags of the contact */
tag_ids?: {
/** Matches if ANY of the tags are present */
$in?: string[];
/** Matches if ALL of the tags are present */
$all?: string[];
};
/** The date the contact was last updated */
updatedAt?: {
/** Minimum date */
$gte?: Date;
/** Maximum date */
$lte?: Date;
};
};
/** The projection of the search results. By default, only the contact_id is returned.
* If you want to return specific fields, you can specify them here.
*/
projection?: Record<ContactField, 1>;

options?: {
/** The number of results to skip */
skip?: number;
/** The number of results to return */
limit?: number;
};
};

Example

{
"find": {
"cell": ["0821234567", "0827654321"],
"tag_ids": {
"$in": ["tag_id_1", "tag_id_2"]
},
"updatedAt": {
"$gte": "2021-01-01T00:00:00.000Z",
"$lte": "2021-12-31T23:59:59.999Z"
}
},
"projection": {
"cell": 1,
"firstname": 1,
"c1": 1
},
"options": {
"skip": 0,
"limit": 10
}
}

Response

Success

200
{
ok: true;
data: {
/** The parsed search query, with default values filled in */
parsed_request: ContactSearchBody;
/** The contacts that matched the search query */
contacts: Contact[];
}
}

Error

400
{
ok: false;
/** Contains detailed information about the validation errors */
error: ZodIssue[];
}
403
{
ok: false;
error: {
code: "Insufficient Resource IDs";
/** The missing resource IDs */
missing: Record<string, string[]>;
}
}

Delete a single contact

DELETE /contacts/:cell

Delete a single contact by their cell number.

  • 🔐 Permissions: ["contact.delete"]

Request

URL Parameters

FieldTypeRequiredDescription
cellstringThe MSISDN of the contact you want to delete.

Response

Success

200
{
ok: true;
}

Error

400
{
ok: false;
error: "Invalid cell number";
}
404
{
ok: false;
error: "Contact not found";
}

Opt out a contact

note

The POST endpoint is more robust. It allows you to opt a contact out of multiple campaigns at once.

The PUT endpoint only allows you to opt a contact out of a single campaign.

POST /contacts/:cell/optOut

Opt out a contact by their cell number.

  • 🔐 Permissions: ["contact.update.deduped_campaign_ids"]

Request

URL Parameters

FieldTypeRequiredDescription
cellstringThe MSISDN of the contact you want to optOut.

Body

FieldTypeRequiredDescription
campaign_idsstring[]The ids of the campaigns you want to opt out the contact from.
allbooleanOpt out the contact from all existing and future campaigns.
create_missing_contactbooleanIf the contact doesn't exist, create it with the given opt-outs. set.

Response

Success

200
{
ok: true;
data: {
matchedCount: number; // The number of contacts that matched the cell number
modifiedCount: number; // The number of contacts that were modified
}
}

Error

400
{
ok: false;
error: "Invalid cell number";
}
400
{
ok: false;
error: "Must provider either campaign_ids or set 'all' flag to true";
}

PUT /contacts/:cell/optOut

Opt out a contact by their cell number.

  • 🔐 Permissions: ["contact.update.deduped_campaign_ids"]

Request

URL Parameters

FieldTypeRequiredDescription
cellstringThe MSISDN of the contact you want to optOut.

Body

FieldTypeRequiredDescription
campaign_idstringThe id of the campaign you want to opt out the contact from.
allbooleanOpt out the contact from all existing and future campaigns.

Response

Success

200
{
ok: true;
data: {
/** The number of contacts that matched the cell number */
matchedCount: number;
/** The number of contacts that were modified */
modifiedCount: number;
}
}

Error

400
{
ok: false;
error: "Invalid cell number";
}

Add or remove tags from a contact

Add or remove tags from a contact by their cell number.

tip

Using the two endpoints below, you can add or remove tags from an existing contact by their cell number.

  • PUT /contacts/:cell/tag/add
  • PUT /contacts/:cell/tag/remove

Both routes take the same input, and return the same output.

  • 🔐 Permissions: ["contact.update.tag_ids"]

Request

URL Parameters

FieldTypeRequiredDescription
cellstringThe MSISDN of the contact you want to add/remove tags from.

Body

FieldTypeRequiredDescription
tag_idsstring[]A list of tag ids you want to add/remove
tagsstring[]A list of tag names you want to add/remove. It is recommended to use tag_ids instead, as tag names can change.
create_missing_contactbooleanIf the contact doesn't exist, create it with the given tags set. Only applies to /contacts/[cell]/tag/add.

Example

{
"tag_ids": ["tag_id_1", "tag_id_2"],
"tags": ["tag_name_1", "tag_name_2"],
"create_missing_contact": true
}

Response

Success

200
{
ok: true;
data: {
matchedCount: number; // The number of contacts that matched the cell number
modifiedCount: number; // The number of contacts that were modified
}
}

Error

400
{
ok: false;
// If your request doesn't contain any tags, or none of the tags supplied are valid
error: "No tags to add/remove";
}

Upload contacts

tip

There are two contact-upload methods.

POST /contacts

  • Will only create new contacts, and is relatively fast.
  • Has a limit of 100_000 contacts per request.
  • Uses fewer rate limit credits.

PUT /contacts

  • Will create new contacts, and update existing contacts. It is slower than POST /contacts, but more flexible.
  • Has a limit of 20_000 contacts per request.
  • Uses more rate limit credits.

Both methods take the same input, and return the same output.

POST /contacts, PUT /contacts

Upload a list of contacts to Dripcel.

  • 🔐 Permissions: ["contact.create"] (for POST), ["contact.update"] (for PUT)

Request

Body

FieldTypeRequiredDescription
contactsContact[]An array of contacts to upload. The default field names must be used, as well as the custom field ids (e.g. c1, c2). In other words, there is no field name mapping. You need to use the exact fields expected by the API.
country'ZA' | 'NA'The country code of the contacts' cell numbers. If specific, you don't have to add the areacode. If not, the areacode is required for each cell.
tag_idsstring[]A list of tags to add to all contacts. You can give different tags to each contact using the tag_ids field or tags field on each contact in the array.
welcome_send_campaign_idstringIf present, trigger the welcome send of the given campaign. Messages will only be sent to contacts that were successfully uploaded.

Example

{
// Parse each contact's `cell` number in South African format
"country": "ZA",
// Will be added to all contacts
"tag_ids": ["680a0b0c0d0e0f0g0h0i0"],
// Trigger the welcome send of this campaign
"welcome_send_campaign_id": "689a0b0c0d0e0f0g0h0i0",
// The contacts to upload
"contacts": [
{
"cell": "0821234567",
"firstname": "John",
"c1": "value1",
"c2": "value2",
// Will only be added to this contact
"tag_ids": ["680a0b0c0d0e0f0g0h0i1"]
},
{
"cell": "0827654321",
"firstname": "Jane",
"c1": "value3",
"c2": "value4",
// You can also refer to tags by name
"tags": ["tag3", "tag4"]
}
]
}

Response

Success

200
{
ok: true;
data: {
// The number of contacts that passed validation
validContacts: number;
// The contacts that failed validation
invalidContacts: ({
row: number; // The 0-based index of the invalid contact in the array
issue: ZodIssue; // The Zod validation error
}[]);
}
}

Bulk Update Contacts

Run a bulk update on your contacts.

POST /contacts/update

  • 🔐 Permissions: ["contact.update"]
danger

This endpoint is quite heavily rate-limited. Although you can update many contacts in one request, you can only make a limited number of requests per minute. Be sure to check for 429 responses and back-off if you hit the rate limit.

Request

Body

tip

The find and update fields use a subset of MongoDB query syntax. You can find more information in the MongoDB documentation.

type ContactBulkUpdateBody = {
// Which contacts to update
find: {
// Match contacts with these cell numbers
cell?: string[];
// Match contacts with these tags
tag_ids?: {
// Match if ANY of the tags are present
$in?: string[];
// Match if ALL of the tags are present
$all?: string[];
};
};

// The update to apply to the matching contacts
// NOTE: Only one of the following fields can be present
// - you can't $addToSet and $pull in the same request
update: {
$addToSet?: {
// Add these tags to the matching contacts
tag_ids?: {
$each: string[];
};
// Dedupe the matching contacts against these campaign_ids
deduped_campaign_ids?: {
$each: string[];
};
};

$pull?: {
// Remove these tags from the matching contacts
tag_ids?: {
$in: string[];
};
};
};
};

Example

{
// Find contacts with these tags
"find": {
"tag_ids": {
"$in": ["tag_id_1", "tag_id_2"]
}
},

// Add these tags to the matching contacts
"update": {
"$addToSet": {
"tag_ids": {
"$each": ["tag_id_3", "tag_id_4"]
}
}
}
}

Response

Success

200
{
ok: true;
data: {
// The number of contacts that matched the query
matchedCount: number;
// The number of contacts that were modified
modifiedCount: number;
// The parsed request. Useful to see what defaults were filled in, and which fields were actually used
parsedRequest: ContactBulkUpdateBody;
}
}

Error

400
{
ok: false;
// Contains detailed information about the validation errors
error: ZodError;
}
403
{
ok: false;
error: {
code: "insufficient_resource_ids";
// The missing resource IDs
missing: Record<string, string[]>;
}
}