Groups, segments and fields
Reading needs Subscribers: view, writing Subscribers: manage.
Groups
Section titled “Groups”| Method and path | What it does |
|---|---|
GET /groups |
Groups by name. filter[name] (name contains), limit, cursor. |
POST /groups |
Creates a group: {"name": "..."}. 201. |
PUT /groups/{id} |
Renames a group: {"name": "..."}. 200. |
DELETE /groups/{id} |
Deletes a group (its subscribers stay). 204. |
GET /groups/{id}/subscribers |
The group’s subscribers (List subscribers). |
POST /groups/{id}/import-subscribers |
Bulk import into the group (Import through the API). |
Create a group
curl -X POST "$ECHO_API/groups" \ -H "Authorization: Bearer $ECHO_TOKEN" -H "Content-Type: application/json" \ -d '{"name":"Webshop vásárlók"}'{"data":{"id":"257e83a2-d55e-4a8c-b9a4-b3e939c151cc","name":"Webshop vásárlók","created_at":"2026-10-22T08:52:08.269421Z","subscribers":0,"total":0,"open_rate":0,"click_rate":0}}Search groups by name
curl -g -H "Authorization: Bearer $ECHO_TOKEN" "$ECHO_API/groups?filter[name]=VIP"{"data":[{"id":"000d6529-0078-40d8-9c29-05cd541c4c2d","name":"VIP vásárlók","created_at":"2026-04-17T12:00:00Z","subscribers":466,"total":495,"open_rate":34.64,"click_rate":7.47,"timed_out":false}],"meta":{"next_cursor":null,"prev_cursor":null,"limit":25,"total":1}}| Key | Meaning |
|---|---|
subscribers |
Active members. |
total |
Members in any status. |
open_rate, click_rate |
The members’ average rates, in percent. |
timed_out |
Lists only: true if counting gave up, and the counts are then null. |
Rename and delete
curl -X PUT "$ECHO_API/groups/257e83a2-d55e-4a8c-b9a4-b3e939c151cc" \ -H "Authorization: Bearer $ECHO_TOKEN" -H "Content-Type: application/json" \ -d '{"name":"Webshop vásárlók 2026"}'curl -X DELETE "$ECHO_API/groups/257e83a2-d55e-4a8c-b9a4-b3e939c151cc" -H "Authorization: Bearer $ECHO_TOKEN"A name already in use answers 409 name_taken. A group that a segment, a campaign or a workflow uses can’t be deleted:
{"error":{"code":"in_use","message":"It's used by these segments: Visszatérő webshop vásárlók"}}Deleting a group sends no subscriber.removed_from_group webhook events for its members.
Segments
Section titled “Segments”Segments are saved filters. Their conditions are edited in the app; the API reads them, renames and deletes them.
| Method and path | What it does |
|---|---|
GET /segments |
Segments by name. filter[name], limit, cursor. |
GET /segments/{id}/subscribers |
The subscribers who match now. |
PUT /segments/{id} |
Renames: {"name": "..."}. Any other key is 422. |
DELETE /segments/{id} |
Deletes. 409 in_use if a campaign or workflow uses it. |
curl -H "Authorization: Bearer $ECHO_TOKEN" "$ECHO_API/segments?limit=1"{"data":[{"id":"026c692e-e106-4bb6-b971-78757cb3fd02","name":"Aktív olvasók (30 nap)","rules":{"version":1,"groups":[[{"type":"email_actions","op":"opened_or_clicked","amount":30}]]},"subscribers":2428,"open_rate":52.88,"click_rate":11.32,"counted_at":"2026-10-22T05:16:28.536739Z","created_at":"2026-05-12T08:00:00Z","updated_at":"2026-05-15T08:00:00Z","timed_out":false}],"meta":{"next_cursor":"bzox","prev_cursor":null,"limit":1,"total":6}}subscribers, open_rate and click_rate are from the last count (counted_at); timed_out is true if the last count gave up and the numbers are older. rules is the segment’s condition set as the app stores it: treat it as read-only.
curl -X PUT "$ECHO_API/segments/6010f9ca-331d-4c81-a3ab-1ed48a62a12b" \ -H "Authorization: Bearer $ECHO_TOKEN" -H "Content-Type: application/json" \ -d '{"name":"Visszatérő webshop vásárlók"}'{"data":{"id":"6010f9ca-331d-4c81-a3ab-1ed48a62a12b","name":"Visszatérő webshop vásárlók","rules":{"version":1,"groups":[[{"type":"groups","op":"belongs_to","values":["257e83a2-d55e-4a8c-b9a4-b3e939c151cc"]}]]},"subscribers":2,"open_rate":0,"click_rate":0,"counted_at":"2026-10-22T08:52:10.230434Z","created_at":"2026-10-22T08:52:10.217956Z","updated_at":"2026-10-22T08:52:10.234278Z","timed_out":false}}Fields
Section titled “Fields”Fields hold the subscribers’ data. Built-in fields (email, name, last_name, company, country, city, phone, state, zip) always exist; custom fields are added per workspace. In subscriber bodies you use the field’s key.
| Method and path | What it does |
|---|---|
GET /fields |
Built-in fields, then custom fields. Not paged. |
POST /fields |
Creates a custom field: {"name": "...", "type": "text" | "number" | "date"}. 201. |
PUT /fields/{key} |
Renames: {"name": "..."}. The key and the merge tag stay. |
DELETE /fields/{key} |
Deletes a custom field and its value from every subscriber. 204. |
curl -H "Authorization: Bearer $ECHO_TOKEN" "$ECHO_API/fields"{"data":[{"key":"email","name":"Email","type":"text","builtin":true,"tag":"{$email}","created_at":null},{"key":"name","name":"Name","type":"text","builtin":true,"tag":"{$name}","created_at":null},{"key":"last_name","name":"Last name","type":"text","builtin":true,"tag":"{$last_name}","created_at":null},{"key":"company","name":"Company","type":"text","builtin":true,"tag":"{$company}","created_at":null},{"key":"country","name":"Country","type":"text","builtin":true,"tag":"{$country}","created_at":null},{"key":"city","name":"City","type":"text","builtin":true,"tag":"{$city}","created_at":null},{"key":"phone","name":"Phone","type":"text","builtin":true,"tag":"{$phone}","created_at":null},{"key":"state","name":"State","type":"text","builtin":true,"tag":"{$state}","created_at":null},{"key":"zip","name":"Zip","type":"text","builtin":true,"tag":"{$zip}","created_at":null},{"key":"szuletesnap","name":"Születésnap","type":"date","builtin":false,"tag":"{$szuletesnap}","created_at":"2026-04-16T06:55:00Z"},{"key":"rendelesek_szama","name":"Rendelések száma","type":"number","builtin":false,"tag":"{$rendelesek_szama}","created_at":"2026-04-16T06:55:00Z"}]}(The answer is shortened: the demo workspace has a few more custom fields.)
Create, rename, delete a custom field
curl -X POST "$ECHO_API/fields" \ -H "Authorization: Bearer $ECHO_TOKEN" -H "Content-Type: application/json" \ -d '{"name":"Kedvenc növény","type":"text"}'{"data":{"key":"kedvenc_noveny","name":"Kedvenc növény","type":"text","builtin":false,"tag":"{$kedvenc_noveny}","created_at":"2026-10-22T08:52:10.268043Z"}}The key is made from the name (lower case, accents removed, spaces to _). Read it from the answer instead of building it yourself.
curl -X PUT "$ECHO_API/fields/kedvenc_noveny" \ -H "Authorization: Bearer $ECHO_TOKEN" -H "Content-Type: application/json" \ -d '{"name":"Kedvenc virág"}'curl -X DELETE "$ECHO_API/fields/kedvenc_noveny" -H "Authorization: Bearer $ECHO_TOKEN"| Error | When |
|---|---|
409 name_taken |
Another field already has this name. |
409 builtin_field |
You tried to rename or delete a built-in field. |
{"error":{"code":"builtin_field","message":"Default fields can't be renamed or deleted."}}Time zones
Section titled “Time zones”GET /timezones lists the IANA time zone names Echo accepts (for example when scheduling a campaign). Any valid token can call it.
{"data":[{"id":"Africa/Abidjan"},{"id":"Africa/Accra"},{"id":"Africa/Addis_Ababa"}]}(Shortened.)