Contact Lists
Full phonebook management — lists, contacts, extra phone numbers, CSV import/export, opt-outs, and one-way Google Contacts sync.
Contact lists power campaigns. Every account auto-creates a default list on first access, so you can add contacts immediately without setup.
#Endpoints
| Method | Path | Description |
|---|---|---|
| GET / POST | /v1/contact-lists/ | List / create contact lists |
| GET / POST | /v1/contact-lists/{listId}/contacts?search= | List (searchable) / add a contact |
| GET / PUT / DELETE | /v1/contact-lists/{listId}/contacts/{contactId} | Get / update (incl. phone) / delete |
| POST / DELETE | /v1/contact-lists/{listId}/contacts/{contactId}/phones[/{phoneId}] | Add / remove additional numbers |
| GET | /v1/contact-lists/{listId}/contacts/export | Stream contacts as CSV |
| POST | /v1/contact-lists/{listId}/import | Bulk import from CSV (row-level error report) |
| GET / POST / DELETE | /v1/contact-lists/google/status|sync|disconnect | One-way Google Contacts import |
All routes in this section require JWT auth — they are dashboard-facing, not developer-API routes.
#Create a list
/v1/contact-lists/JWTcurl -s -X POST https://api.sendafrica.online/v1/contact-lists/ \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Dar es Salaam customers"}'#Add a contact
/v1/contact-lists/{listId}/contactsJWTcurl -s -X POST https://api.sendafrica.online/v1/contact-lists/1/contacts \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Amina",
"last_name": "Juma",
"phone": "0712345678",
"email": "amina@example.co.tz"
}'Adding a phone that already exists in the same list returns 409 duplicate_contact. Use the extra-phones endpoints to attach multiple numbers to one person.
#CSV import
/v1/contact-lists/{listId}/importJWTSend multipart/form-data with a file field. The response includes a row-level error report so partial imports are actionable:
curl -s -X POST https://api.sendafrica.online/v1/contact-lists/1/import \
-H "Authorization: Bearer $JWT_TOKEN" \
-F "file=@contacts.csv"{
"success": true,
"data": {
"imported": 482,
"skipped": 3,
"errors": [
{ "row": 17, "error": "invalid_phone_number" },
{ "row": 92, "error": "duplicate_contact" },
{ "row": 210, "error": "missing phone column" }
]
}
}#Google Contacts sync
A one-way import from Google Contacts into a chosen list (gated by ENABLE_GOOGLE_CONTACTS_SYNC). It uses a separate OAuth scope from login/linking, requires a verified connection, and never writes back to Google:
# Check connection status
curl -s https://api.sendafrica.online/v1/contact-lists/google/status \
-H "Authorization: Bearer $JWT_TOKEN"
# Trigger a sync
curl -s -X POST https://api.sendafrica.online/v1/contact-lists/google/sync \
-H "Authorization: Bearer $JWT_TOKEN"
# Disconnect
curl -s -X POST https://api.sendafrica.online/v1/contact-lists/google/disconnect \
-H "Authorization: Bearer $JWT_TOKEN"#Opt-outs
Contacts who reply STOP are flagged as opted-out and excluded from campaign sends. Respect opt-outs in your own direct API sends too — repeated sends to opted-out numbers risk sender-ID blacklisting.