Contact groups
Organize customers into groups for campaigns and automations.
Contact groups let you organize customers for targeted campaigns and automations. Members can be added by email -- if a customer with that email does not exist, one is created automatically. Group IDs start with grp_ and membership IDs with cgm_.
List groupsGET/v1/contact-groups
Permission: read. Returns groups newest first with { data, pagination: { limit, offset, total } }. Deleted groups are soft-deleted (is_active: false) and are still listed unless you pass is_active=true.
| Query param | Type | Default | Description |
|---|---|---|---|
| search | string | -- | Case-insensitive match on name or description. |
| is_active | boolean | -- | true for active groups only, false for deleted groups only. Omit to get both. |
| limit | number | 50 | Max 100. |
| offset | number | 0 | Offset pagination. |
Get a groupGET/v1/contact-groups/{id}
Permission: read. Returns { data: group } (id, account_id, name, description, color, is_active, total_contacts, metadata, created_by, created_at, updated_at). Soft-deleted groups are returned too. 404 if the group is not in your account.
Create a groupPOST/v1/contact-groups
Permission: write. Returns 201 with { data: group, message }. Returns 400 if name is missing and 409 if a group with the same name already exists in the account (including a soft-deleted one).
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Group name (trimmed). Unique within the account. |
| description | string | No | Description. |
| color | string | No | Hex color. Default: #16a349. |
| metadata | object | No | Arbitrary JSON. Default: {}. |
Update a groupPATCH/v1/contact-groups/{id}
Permission: write. Accepts name, description, color, is_active and metadata; send only the fields you want to change. An empty name is ignored. Setting is_active to true restores a deleted group. Returns { data: group, message }. Returns 404 if the group is not in your account and 409 if another group already has the new name.
Delete a groupDELETE/v1/contact-groups/{id}
Permission: write. Soft-deletes the group (sets is_active to false); members are kept. Returns { message }. 404 if the group is not in your account.
List membersGET/v1/contact-groups/{id}/members
Permission: read. Returns memberships newest first with { data, pagination: { limit, offset, total } }. Each item is a membership row (its id is the memberId used to remove it) with the customer embedded as customer: { id, email, phone, name, avatar_url, created_at }.
| Query param | Type | Default | Description |
|---|---|---|---|
| search | string | -- | Case-insensitive match on the customer email or name. |
| limit | number | 50 | Max 100. |
| offset | number | 0 | Offset pagination. |
Add membersPOST/v1/contact-groups/{id}/members
Permission: write. Send either emails or contacts (if both are sent, contacts wins). For each contact: looks up the customer by email in your account or creates it, then adds it to the group. Existing customers are never overwritten: name and phone are only filled in when they are empty (or the name is still the email placeholder).
| Field | Type | Required | Description |
|---|---|---|---|
| emails | string[] | Conditional | Emails to add. Required if contacts is not sent. |
| contacts | array | Conditional | Array of { email, name?, phone? }. Required if emails is not sent. New customers get this name (default: the part of the email before @) and phone. |
| source | string | No | Stored as customer.source when a new customer is created: api, newsletter, form, import or manual. Default: api. Any other value returns 400. |
| origin | string | No | Free text (max 100 characters) saved on the membership as metadata.origin, e.g. "landing-page". |
- added -- new members created in the group.
- skipped -- contacts that were already members (or empty emails).
- errors -- per-email failures with a reason (invalid email format, failed to create customer, failed to add to group).
- Emails are trimmed and lowercased. Returns 400 if neither emails nor contacts has at least one entry, and 404 if the group is not in your account.
- Each newly added member fires the "Contact added to group" automations configured for this group.
DELETE/v1/contact-groups/{id}/members/{memberId}
Permission: write. Permanently removes the member from the group (the customer itself is not deleted). memberId is the membership id (cgm_...) returned by GET members, not the customer id. Returns { message }, or 404 if the group or the membership is not found.