Message API - Read
Use the read endpoints to retrieve messages from your account. You can list messages with filtering, sorting, and pagination, or retrieve a single message by ID, optionally with its HTML.
Endpoints
Section titled “Endpoints”| Method | URL | Description |
|---|---|---|
| GET | https://e1.envoke.com/v2/messages |
Return a list of messages. |
| GET | https://e1.envoke.com/v2/messages/{ID} |
Return a single message. |
Authentication is via HTTP Basic Auth using your API ID and API Key.
List Messages
Section titled “List Messages”GET https://e1.envoke.com/v2/messagesReturns a JSON array of messages, most recently modified first. Supports filtering, sorting, pagination, and field selection.
The list contains every message in your account that has not been deleted, in every status: drafts, scheduled and sent messages, messages published to the archive, and the Nurture and Transactional messages set up in Envoke. Templates and deleted messages are not included. There is no filter by message type.
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 10 |
Maximum number of results to return. Hard cap is 100 unless ?fields= or ?result_type=kvp is also set (see note below). limit=1 returns a single object, not an array (see below). |
skip |
integer | 0 |
Number of records to skip. Use with limit and sort to paginate. |
fields |
string | (all) | Comma-separated list of fields to include in each result, e.g. id,name,status. Use names from the Fields reference. |
result_type |
string | (array) | Set to kvp to receive an object of message ID to name ({ "2001": "Spring Season Announcement" }). |
filter[{field}] |
string | — | Filter on a field. See Filterable and sortable fields and Filter Operators. |
sort[{field}] |
string | modified_time descending |
Sort on a field. Value: asc or desc (case-insensitive), or 1 or -1. Repeat for a secondary sort. A sort replaces the default order. |
Note — limit behaviour with ?fields= and ?result_type=kvp: When either of these parameters is present, the default limit increases to 10,000 (returning every record up to that number if no explicit limit is specified) and a ?limit= value above 100 is honoured as-is.
Note — limit=1 returns an object. With limit=1 the response is the matching message as a bare JSON object, not an array of one. result_type=kvp has no effect when limit=1; fields still applies. When nothing matches, the response is [].
Note — filters without filter[...]. When the request has no filter parameter, every query parameter other than limit, skip, sort, fields, result_type, and include_html is treated as a filter, so ?status=Sent is the same as ?filter[status]=Sent. Any other parameter is rejected as an unknown filter field (for example Field 'folder' is not valid for filtering). When filter is present, the other parameters are ignored as filters.
include_html has no effect on the list; HTML is returned only for a single message.
Filterable and sortable fields
Section titled “Filterable and sortable fields”| Field | Filter operators | Sortable |
|---|---|---|
id, external_id, name, subject |
equals, (ne) |
Yes |
status |
equals, (ne) |
Yes, by status code |
language, recipient_language |
equals, (ne) |
Yes, by language ID |
publish_archive, utm_tag_links |
equals, (ne) |
Yes |
create_time, modified_time |
— | Yes |
Fields not in this table cannot be filtered or sorted, including group, send_time, sender, reply_to, recipient_subscription, recipient_tag, and recipient_segment. To find messages by one of these, list with fields and select on your side.
nameandsubjectmatch the whole value. Case is ignored.statustakes a status name or code; see Filter by status.languageandrecipient_languagetake the language ID, not the code:1for English,3for French.filter[language]=endoes not match English messages.publish_archivetakes the stored value:2for messages published to the archive,1for the rest.trueandfalsedo not work in filters.utm_tag_linkstakes1for messages with UTM tagging on and0for off.trueandfalsedo not work in filters; use1or0.
Filter Operators
Section titled “Filter Operators”| Operator | Example | Description |
|---|---|---|
| (none) | ?filter[subject]=Our spring season is here |
Equals. |
(ne) |
?filter[status][(ne)]=Draft |
Not equal. |
(or) |
?filter[(or)][0][status]=Sent&filter[(or)][1][status]=Scheduled |
Matches if any of the grouped conditions match. |
(not) |
?filter[(not)][status]=Sent |
Matches if the grouped conditions do not all match. |
Note: URL-encode brackets in production requests (e.g. %5B for [).
Each operator also has a $ spelling ($ne, $or, $not) that behaves the same way. These docs use the (op) spelling.
The (in), (regex), (gt), (lt), (gte), and (lte) operators are not supported on any message field. They fail with an error that names the SQL operator, e.g. 'IN' is not a valid operator for the field 'status' (REGEXP for (regex); >, <, >=, <= for the range operators). To match one of several values, use (or).
Combining conditions.
- Separate filters are ANDed:
?filter[status]=Draft&filter[language]=3. - A query string cannot repeat a key, so to use the same field twice, put each condition in its own numbered group:
?filter[0][status][(ne)]=Draft&filter[1][status][(ne)]=Sent. Groups inside(or)are numbered the same way. (not)wraps everything inside it:?filter[(not)][status]=Sent&filter[(not)][language]=3excludes messages that are both sent and French.
Filter by status
Section titled “Filter by status”status can be filtered by name or by code.
| Name | Code |
|---|---|
Draft |
0 |
Scheduled |
1 |
AB test in progress |
2 |
Queuing |
4 |
Sending |
5 |
Transactional |
7 |
Nurture |
8 |
Sent |
9 |
- Names are matched ignoring case and surrounding spaces, and a space and an underscore are treated as the same:
Sent,sent,AB test in progress, andab_test_in_progressall work. - A code is used as given. A number that is not a status code (e.g.
3) is accepted and matches nothing. - An unknown name fails with the list of names:
Invalid 'status' provided (possible values: 'Draft', 'Scheduled', 'AB test in progress', 'Queuing', 'Sending', 'Transactional', 'Nurture', 'Sent'). (ne)works with names and codes.- To match several statuses, use
(or):?filter[(or)][0][status]=Sent&filter[(or)][1][status]=Scheduled.(in)is not supported.
Errors
Section titled “Errors”Invalid list parameters return HTTP 400. The limit, skip, and sort format errors are returned first; filter and sort field errors are then listed together:
{ "success": false, "result_text": "Validation failed, see 'result_data' -> 'errors'", "result_data": { "errors": [ "Field 'folder' is not valid for filtering", "'IN' is not a valid operator for the field 'status'" ] }}| Error | Cause |
|---|---|
Invalid 'limit': 'ten' |
limit is not a whole number. |
Invalid 'skip': 'abc' |
skip is not a whole number. |
Invalid 'sort': 'name' |
sort was sent without a field, e.g. ?sort=name. |
'up' is not a valid sort direction |
Sort direction is not asc, desc, 1, or -1. |
Field 'folder' is not valid for sorting |
The field does not exist. |
Field 'folder' is not valid for filtering |
The field does not exist. Also returned for an unrecognised operator: ?filter[name][(foo)]=x gives Field '(foo)' is not valid for filtering. |
'IN' is not a valid operator for the field 'status' |
The operator is not supported. The message names the SQL operator: IN, REGEXP, >, <, >=, or <=. |
Invalid 'status' provided (possible values: ...) |
Not a status name. The message lists the valid names. |
Field 'name' requires a scalar value |
An operator is given a list or group where a single value is expected, e.g. filter[name][(ne)][]=Gala. |
Response
Section titled “Response”A JSON array of message objects. Returns an empty array ([]) if no messages match.
[ { "id": "2001", "external_id": "3e8b1f6c9a2d4e7b0c5f8a1d3e6b9c2f", "preview_url": "https://engage.envoke.com/m/a7c3e9f1b5d2/m/3e8b1f6c9a2d4e7b0c5f8a1d3e6b9c2f", "create_time": "2026-10-06 10:15:42", "modified_time": "2026-10-06 11:02:08", "name": "Spring Season Announcement", "group": "Productions", "status": "Scheduled", "send_time": "2026-10-20 09:00:00", "sender": "Box Office <boxoffice@example.org>", "reply_to": "Front of House <frontofhouse@example.org>", "subject": "Our spring season is here", "language": "en", "recipient_subscription": "Season News", "recipient_tag": "", "recipient_segment": "", "recipient_language": "", "publish_archive": true, "utm_tag_links": true }]Times are in the account time zone with no offset (see Dates and time zones). html is never included in list responses.
Get a Single Message
Section titled “Get a Single Message”GET https://e1.envoke.com/v2/messages/{ID}Returns a single message object (the same shape as one item in the list response). Replace {ID} with the Envoke message ID. fields can be used to select fields; filter, sort, paging, and result_type parameters are ignored.
Add ?include_html=1 to include the message HTML. It is added as the last key, html. With include_html=0 or without the parameter, the HTML is left out. When fields is also set, list html in it to keep the HTML.
If the ID is not found, or belongs to a deleted message or a template, the API returns an empty array ([]).
Response with ?include_html=1
Section titled “Response with ?include_html=1”{ "id": "2003", "external_id": "9c4d2a7e1f5b3d8a6c0e4f2b7d9a1c5e", "preview_url": "https://engage.envoke.com/m/a7c3e9f1b5d2/m/9c4d2a7e1f5b3d8a6c0e4f2b7d9a1c5e", "create_time": "2026-10-06 10:40:11", "modified_time": "2026-10-06 10:40:11", "name": "Pirates of Penzance - Opening Night", "group": "", "status": "Draft", "send_time": "", "sender": "Box Office <boxoffice@example.org>", "reply_to": null, "subject": "", "language": "en", "recipient_subscription": "", "recipient_tag": "", "recipient_segment": "", "recipient_language": "", "publish_archive": false, "utm_tag_links": false, "html": "<html><body><h1>The Pirates of Penzance</h1><p>Curtain at 7:30 p.m.</p></body></html>"}Examples
Section titled “Examples”Return the first page of messages
Section titled “Return the first page of messages”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages"Returns the 10 most recently modified messages. Use limit (up to 100) and skip to page through the rest.
Paginate through results
Section titled “Paginate through results”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?sort%5Bid%5D=asc&limit=100&skip=100"Sort by name
Section titled “Sort by name”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?sort%5Bname%5D=asc&limit=5"Find a message by name
Section titled “Find a message by name”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?filter%5Bname%5D=Spring%20Season%20Announcement"Filter by subject
Section titled “Filter by subject”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?filter%5Bsubject%5D=Our%20spring%20season%20is%20here"Sent messages, by status name
Section titled “Sent messages, by status name”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?filter%5Bstatus%5D=Sent"The same filter by status code:
curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?filter%5Bstatus%5D=9"Everything except drafts
Section titled “Everything except drafts”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?filter%5Bstatus%5D%5B%28ne%29%5D=Draft"Sent or scheduled messages
Section titled “Sent or scheduled messages”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?filter%5B%28or%29%5D%5B0%5D%5Bstatus%5D=Sent&filter%5B%28or%29%5D%5B1%5D%5Bstatus%5D=Scheduled"Messages published to the archive
Section titled “Messages published to the archive”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?filter%5Bpublish_archive%5D=2"Return only specific fields
Section titled “Return only specific fields”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?fields=id,name,status,send_time"Response:
[ { "id": "2002", "name": "Auditions Open", "status": "Draft", "send_time": "" }, { "id": "2001", "name": "Spring Season Announcement", "status": "Scheduled", "send_time": "2026-10-20 09:00:00" }]With fields set and no limit, this returns up to 10,000 messages.
Return as a key-value map
Section titled “Return as a key-value map”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?result_type=kvp"Response:
{ "2002": "Auditions Open", "2001": "Spring Season Announcement" }Look up one message’s ID by name
Section titled “Look up one message’s ID by name”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages?name=Auditions%20Open&fields=id,status&limit=1"Response (an object, because limit=1):
{ "id": "2002", "status": "Draft" }Get a single message by ID
Section titled “Get a single message by ID”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages/2001"Get a single message with its HTML
Section titled “Get a single message with its HTML”curl -X GET -gs -u "$API_ID:$API_KEY" \ "https://e1.envoke.com/v2/messages/2003?include_html=1"Note: The curl examples above are formatted for readability. All requests must use properly encoded URLs.
Full reference, OpenAPI description, and Postman collection: developers.envoke.com.

