Developer docs
API reference
Endpoints for conversations, tags, and customers — plus the JSON object shapes they return.
All paths are relative to https://api.replyplex.com/public/v1. Mutating endpoints are marked
(write) and need a write-scoped key.
A machine-readable OpenAPI spec is published at
/public/v1/openapi.json, with an interactive
viewer at /public/v1/docs — point your codegen/SDK
tooling at it.
Conversations
List conversations
GET /conversations
Provide one of:
q— a search query (matches subject, customer, and message bodies; supports the samestatus:/assignee:/tag:operators as the console search). Not paginated, butlimitis honoured (default 50, max 100), andinboxnarrows the search to one mailbox.cursorandupdatedAfterare rejected with a 400 rather than ignored.inbox— an inbox id, paginated. Extra params:status=ACTIVE|PENDING|CLOSED|SNOOZED|SPAM,limit(default 50, max 100),updatedAfter(ISO-8601, incremental sync), andcursor.
The body is a plain array of conversation summaries, ordered
newest-created first. When more pages exist, the response carries X-Next-Cursor (pass it
back as cursor) and a GitHub-style Link: …; rel="next". Iterate until there’s no
X-Next-Cursor; for incremental sync, pass the last timestamp you processed as updatedAfter.
# page 1 — read the cursor from the response headers
curl -si -H "Authorization: Bearer $RP_KEY" \
"https://api.replyplex.com/public/v1/conversations?inbox=$INBOX&limit=50" | grep -i x-next-cursor
# page 2
curl -H "Authorization: Bearer $RP_KEY" \
"https://api.replyplex.com/public/v1/conversations?inbox=$INBOX&cursor=$CURSOR"
Get one conversation
GET /conversations/:id
Returns a full conversation including messages, activity, and customFields.
Create a conversation (write)
POST /conversations
Body — an outbound message that starts a new ticket:
{
"inboxId": "uuid",
"to": "customer@example.com",
"subject": "Welcome!",
"bodyText": "Hi there…",
"bodyHtml": "<p>Hi there…</p>",
"cc": [],
"bcc": [],
"mode": "SEND",
"attachments": []
}
mode is one of SEND, SEND_AND_PENDING, SEND_AND_CLOSE, SEND_AND_SNOOZE. Returns the created
conversation. The inbox’s sending domain must be verified.
Reply to a conversation (write)
POST /conversations/:id/reply
{
"bodyText": "Thanks for reaching out…",
"bodyHtml": "<p>Thanks…</p>",
"cc": [],
"bcc": [],
"mode": "SEND",
"attachments": [],
"scheduledFor": "2026-07-21T13:00:00.000Z",
"savedReplyIds": []
}
Two optional fields:
scheduledFor— ISO 8601 datetime. When set, the reply is held instead of sent immediately (its message returns withdeliveryState: "scheduled"and ascheduledFortimestamp) and dispatches at that time. Must be in the future, at most 30 days ahead. Composes withmode— a scheduledSEND_AND_CLOSEcloses the conversation when the reply actually sends, not when you queue it.savedReplyIds— up to 20 saved-reply UUIDs that were used composing this reply. Recorded on thereply_sentevent and powers the analytics “Saved replies used” report. Insertion semantics: include a saved reply’s id even if the text was edited afterwards.
Add an internal note (write)
POST /conversations/:id/notes
Adds an internal note — no email is sent — and fires a message.created webhook with
internalNote: true.
{
"bodyText": "Called the customer — they'll send logs.",
"mentions": []
}
Assign (write)
POST /conversations/:id/assign
{ "assigneeId": "uuid" }
Send "assigneeId": null to unassign.
Add / remove a tag (write)
POST /conversations/:id/tags { "tagId": "uuid" }
DELETE /conversations/:id/tags/:tagId
Close / reopen (write)
POST /conversations/:id/close
POST /conversations/:id/reopen
Update properties (write)
PATCH /conversations/:id
Set any subset of a conversation’s properties (at least one required). Omitted fields are left
untouched; to unsnooze, call reopen.
{
"priority": "HIGH",
"snoozedUntil": "2026-08-01T09:00:00Z",
"inboxId": "uuid",
"customFields": [{ "fieldId": "uuid", "value": "Enterprise" }]
}
priority—LOW/NORMAL/HIGH/URGENT, ornullto clear.snoozedUntil— ISO 8601, must be in the future.inboxId— move to another inbox.customFields— set values byfieldId(value: nullclears one).
All mutation endpoints return the updated conversation.
Tags
GET /tags
Returns the workspace’s tags.
Customers
GET /customers?q=<name-or-email>
Returns matching customers: an array of { "id", "name", "email" }.
Reference data
Read endpoints for resolving the ids the write endpoints need.
GET /inboxes # the org's live inboxes: { id, name, sendingDomainVerified }
GET /inboxes/:id/members # assignable agents for an inbox (resolve assigneeId)
GET /saved-replies # saved replies available to the key
GET /custom-fields # custom-field definitions: { id, label, type, entity }
Join a conversation’s customFields[].fieldId to the definitions, and use an inbox id as the
inbox / inboxId param when listing or creating.
Object shapes
Conversation summary
{
"id": "uuid",
"number": 1234,
"inboxId": "uuid",
"subject": "Refund not received",
"status": "ACTIVE",
"priority": "HIGH",
"customerEmail": "a@b.com",
"customerName": "James Carter",
"assigneeId": "uuid | null",
"assigneeName": "Emily Turner | null",
"teamId": "uuid | null",
"teamName": "Billing | null",
"tags": ["Billing", "Bug"],
"lastMessageAt": "2026-07-09T12:00:00.000Z | null",
"preview": "…latest message excerpt…",
"createdAt": "2026-07-01T…"
}
status is ACTIVE|PENDING|CLOSED|SNOOZED|SPAM; priority is LOW|NORMAL|HIGH|URGENT or null.
Conversation
The summary above plus:
{
"tags": [ "…full Tag objects…" ],
"following": false,
"snoozedUntil": "… | null",
"csatRating": "GOOD | NEUTRAL | BAD | null",
"csatComment": "… | null",
"messages": [ "…thread messages: direction, sender, to, cc, bodyText, bodyHtml, createdAt, attachments…" ],
"activity": [ "…timeline events…" ],
"customFields": [ { "fieldId": "uuid", "value": "…" } ]
}
Custom-field values are keyed by fieldId; the field’s label/type live in its definition (managed in
Settings → Custom fields).
Tag
{ "id": "uuid", "name": "Billing", "type": "WORKFLOW", "color": "#F79009 | null" }