SendAfrica logoSendAfricaDocs

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

MethodPathDescription
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/exportStream contacts as CSV
POST/v1/contact-lists/{listId}/importBulk import from CSV (row-level error report)
GET / POST / DELETE/v1/contact-lists/google/status|sync|disconnectOne-way Google Contacts import

All routes in this section require JWT auth — they are dashboard-facing, not developer-API routes.

#Create a list

POST/v1/contact-lists/JWT
bash
bash
curl -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

POST/v1/contact-lists/{listId}/contactsJWT
bash
bash
curl -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

POST/v1/contact-lists/{listId}/importJWT

Send multipart/form-data with a file field. The response includes a row-level error report so partial imports are actionable:

bash
bash
curl -s -X POST https://api.sendafrica.online/v1/contact-lists/1/import \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -F "file=@contacts.csv"
200 OK
json
{
  "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:

bash
bash
# 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.