Contacts and groups

Your saved numbers, and the groups you organise them into. The same records the dashboard shows — there is one contact list per organization, not one per surface.

Test keys are read-only here. A test key can list contacts, groups and templates, but any write returns 403 FORBIDDEN. Test keys get pasted into sample code and CI configs; one of them deleting your live contact list is not a trade worth making. Use a live key to write.

List contacts

GET/api/v1/contacts
Query parameters
search
string
Matches against name and phone number.
group_id
string
Only this group's members.
limit
integer
1–200. Defaults to 100.
cursor
string
The next_cursor from the previous page.
Response200
JSON
{
  "success": true,
  "data": [
    {
      "id": "cmuawlglj000pbuwqoponkvjt",
      "phone": "+233271231111",
      "first_name": "Yaw",
      "last_name": "Asante",
      "email": null,
      "groups": [{ "id": "cmuawlgkf000bbuwq57ilhdds", "name": "Regulars" }],
      "created_at": "2026-09-21T07:08:10.951Z"
    }
  ],
  "next_cursor": "cmuawlglj000pbuwqoponkvjt"
}

Pagination is cursor-based, not offset-based. At scale an OFFSET 500000 is a table scan; a cursor is an index seek. Keep requesting until next_cursor is null.

Create a contact

POST/api/v1/contacts
Parameters
phone
stringrequired
024…, 233… or +233…. Stored normalised, so the same person cannot be added twice in two formats.
first_name
string
Up to 80 characters.
last_name
string
Up to 80 characters.
email
string
Optional.
group_ids
string[]
Up to 20 groups to add them to.

Update a contact

PATCH/api/v1/contacts/:id

Send null to clear a field and omit it to leave it alone. The phone number cannot be changed — it is the contact's identity and carries their message history. Delete and re-add instead.

Delete a contact

DELETE/api/v1/contacts/:id

Import a CSV

POST/api/v1/contacts/import
Parameters
csv
stringrequired
The file contents, up to 6MB. The first row must be headings.
group_id
string
Add every imported contact to this group.
update_existing
boolean
Update names for numbers already on file. Defaults to false, which leaves them untouched.

The phone column may be called phone, mobile, msisdn, number or contact. Any column we do not recognise is kept and can be used as a {{placeholder}} when you send. Invalid rows come back with their row number rather than failing the whole file.

Export a CSV

GET/api/v1/contacts/export

Returns text/csv, not JSON. Values beginning =, +, - or @ are escaped so a contact named =HYPERLINK(...) cannot execute when the file is opened in a spreadsheet.

Groups

GET/api/v1/contacts/groups
POST/api/v1/contacts/groups
POST/api/v1/contacts/groups/:id/members
DELETE/api/v1/contacts/groups/:id
Shell
# Add contacts to a group
curl -X POST https://api.jkasms.com/api/v1/contacts/groups/GROUP_ID/members \
  -H "Authorization: Bearer $JKASMS_SECRET_KEY" \
  -H "X-JKASMS-Org-Id: $JKASMS_ORG_ID" \
  -H "Content-Type: application/json" \
  -d '{ "contact_ids": ["cmuawlglj000pbuwqoponkvjt"] }'

Deleting a group never deletes the contacts inside it. Contact ids that belong to another organization are silently excluded rather than linked.