Messages
Read and organize messages from code: check what's unread, search everything, archive what's done and snooze what can wait.
These requests take an API token, not a send key. A read-only token can list, read, search and watch. Changing anything takes full access.
List your messages
Ask for what's unread:
Ripple returns a page of messages, newest activity first, with a total and a nextCursor for the next page:
A message has more fields than this; the API reference lists them all. Three filters narrow the list:
| Filter | Shows |
|---|---|
in | all, the default: everything not archived or snoozed. archive: archived messages. snoozed: snoozed messages, soonest to return first. |
sourceId | One source's messages. Inbox is a source too; its ID is in the list of sources, with kind system. |
unread | true for unread messages, false for read ones |
A message's source says where it belongs. Its sound is the one its sender chose, or null when it plays its source's or the account's.
How threads appear
A thread appears once in a list, as its latest message. Its thread field describes the whole conversation, and previousMessage shows the update before the latest, if there is one. A thread is read or unread as a whole.
Read a message or a thread
To open one message in full, with its body and history:
For a message in a thread, the response also has the thread's newest messages in timeline. To read further back, pass its timelineCursor as cursor to GET /v1/. To read the thread up to the message you asked for, pass requestedMessage.cursor instead.
Search
Search looks through titles, bodies, thread names and source names. Send the query as JSON:
Unlike a list, search covers everything but Trash, archived and snoozed messages included. The best matches come first. These fields narrow the results:
| Field | Narrows to |
|---|---|
in | all, archive or snoozed |
sourceIds | Any of these sources, up to 100 |
after, before | A date range |
alert | quiet, standard or important |
unread | true for unread, false for read |
Send "sort": "newest" to order by date. Filters also work without a query, which makes search a flexible list, newest first:
A message you just sent can take a moment to show up in search.
Get the next page
Lists, searches and threads page the same way. While a response's nextCursor isn't null, send it back as cursor, with the same filters, for the next page.
- A list or a thread takes it in the address:
?cursor=… - A search takes it in the body:
"cursor": "…"
limit sets the page size, up to 100. Pass cursors back exactly as you got them; one from a different list or search gets 400 invalid_cursor.
A search returns at most about 1,000 results. Past that, the response says "truncated": true and stops giving a nextCursor. Narrow the query or filters to reach the rest.
Watch for new messages
To act on messages as they arrive, without asking over and over, keep a stream open. Ripple sends each new message the moment it accepts it, as Server-Sent Events:
Add sourceId for one source's new messages. Each message event's data is one line of JSON: the message as reading it shows it, without sourceState or sourceDeletedAt. A new message in a thread comes with the thread's title in thread.title and the update before it in previousMessage. Only arrivals send events, not reading, archiving, snoozing, moving or Trash, and a message already in Trash when its event would go out is skipped. Ignore events with other names.
A stream starts at the present, and the connection can close at any time, such as after 15 minutes. Every event has an id; one without data only moves your place forward. To pick up where you left off, reconnect with the last id in a Last-Event-ID header, and every new message since then arrives, for up to 30 days. Many SSE clients do this for you.
| Error | What to do |
|---|---|
410 last_event_id_expired | The Last-Event-ID is too old or unusable. Reconnect without it, and list messages to catch up. |
429 message_stream_limit | Too many streams are open. Wait the Retry-After seconds and try again. |
ripple messages watch does all of this for you.
Organize messages
To mark messages read or unread, archive or unarchive them, or move them to Trash, post their IDs to the matching address, up to 100 at a time:
| Address | Does |
|---|---|
/v1/ | Marks read |
/v1/ | Marks unread |
/v1/ | Archives |
/v1/ | Brings back from the archive |
/v1/ | Moves to Trash, where messages stay 30 days before they're deleted for good |
Each response's changedCount counts only what that request changed. A message in a thread acts on the whole thread, and every message keeps its source. Trashed messages can be restored until they're deleted.
Move a message to another source
A message outside a thread can move to another source. Post this to /v1/:
Threads stay in the source they started in.
Snooze a message
Snoozing hides a message until a time you choose, then brings it back with an alert. Send the return time, with its offset from UTC, to the message's snooze address:
You can also send timeZone, the zone to show the time in when the snooze is edited later, and alert, how the message returns. Ripple fills in sensible values for either one you leave out.
To bring a message back early, send a DELETE to the same address, with no body.
To act only on the message as you last saw it, send its revision as expectedRevision: in a snooze's body, or as ?expectedRevision= when you cancel one. If the message has changed, Ripple answers 409 message_changed with the message as it is now in current, and changes nothing.
Restore from Trash
Trash keeps deleted messages, threads and sources for 30 days. Each item's purgeAt says when it will be deleted for good.
| To | Send |
|---|---|
| See what's there | GET /v1/, with type=message, thread, source or content (messages and threads) to narrow it |
| Search it | POST /v1/, with the same fields as message search except in |
| Open an item | GET /v1/ or GET /v1/ |
| Restore an item | POST /v1/ |
| Delete it for good | DELETE /v1/, with no body |
For restoring and deleting, kind is messages, threads or sources.
Deleting from Trash can't be undone. To make sure the item is still the one you looked at, send its deletedAt as ?deletedAt=; a restore takes it in its JSON body. If it no longer matches, Ripple answers 404 not_found and does nothing.
When a request fails
Errors have the same shape everywhere: a code to match on and a message for people, as in Send messages. A few add a field, such as current on 409 message_changed.
If a request times out, or fails on Ripple's side, the change may still have happened. Read the current state before trying again. A busy search answers 503 with search_busy or search_timeout; wait the Retry-After seconds and try again.
The API reference has every operation's fields, limits and errors.