OmniStream Docs
  • Dokumentasi
  • Developer
  • API Reference
Information
Auth
    Login with email and passwordpostRequest a password-reset code (agent)postSet a new password with a reset code (agent)postGet current agent profilegetLogout (clears cookie)postAdvertise available SSO login methodsgetBegin Google SSO logingetGoogle SSO callback (OIDC redirect URI)getDiscover company SSO availability for an emailpostBegin company SSO login (ticket from /discover)getCompany SSO callback (OIDC redirect URI)getBegin a passkey (WebAuthn) login ceremonypostComplete a passkey loginpostBegin passkey registration for the current agentpostComplete passkey registrationpostList the current agent's passkeysgetDelete one of the current agent's passkeysdeleteList company SSO providersgetCreate a company SSO providerpostUpdate a company SSO providerputDelete a company SSO providerdeleteIssue a fresh JWT for the current sessiongetRegister a new tenant organizationpost
Conversations
    List conversationsgetGet a single conversationgetAssign or unassign an agentpatchAdd an assignee (human agent or AI agent) to a conversationpostRemove an assignee (human agent or AI agent) from a conversationdeleteUpdate conversation statuspatchMark conversation as readpostExpire stale conversationspostUpdate conversation tagspatchTakeover a conversationpostBulk conversation actionspost
Messages
    List messages in a conversationgetSend an outbound messagepostSend a WhatsApp template message in one callpostSearch messages across conversationsget
Contacts
    List contactsgetImport contacts from a CSV filepostPreview a CSV before importing (wizard step 1)postImport contacts from CSV with explicit column mapping (wizard step 2)postGet a contact by IDgetUpdate a contactpatchList conversations for a contactget
Outgoing Webhooks
    List outgoing webhooksgetCreate an outgoing webhookpostList available webhook event typesgetAggregated delivery statisticsgetBulk-replay deliveries by idpostReplay all dead-lettered deliveriespostReplay a single deliverypostDelete an outgoing webhookdeleteUpdate an outgoing webhookpatchList deliveries for a webhookgetSend a test event to the webhookpostStart a signing-secret rotationpostComplete a pending secret rotationpostCancel a pending secret rotationpost
WA Templates
    List WhatsApp message templatesgetCreate a WhatsApp message templatepostSync templates from MetapostGet a WhatsApp template by IDgetEdit a template (status-aware; re-submits to Meta)putDelete a WhatsApp template (Meta-first)deleteBulk-send an approved template to a list of contactspostUpdate template header media URLpatch
Schemas
OmniStream CRM API
OmniStream CRM API

Messages

Endpoint

Message retrieval and sending


List messages in a conversation

GET
https://api-chat.misindo.id
/api/conversations/{id}/messages

Cursor-paginated. Returns newest first.

List messages in a conversation › path Parameters

id
​string · uuid · required

List messages in a conversation › query Parameters

cursor
​string

MongoDB ObjectId hex string for pagination

limit
​integer · min: 1 · max: 100
Default: 50

List messages in a conversation › Responses

200

Paginated messages

​object[] · required
has_more
​boolean · required
next_cursor
​string

MongoDB ObjectId hex for next page

GET/api/conversations/{id}/messages
curl --request GET \ --url https://api-chat.misindo.id/api/conversations/:id/messages
shell
Example Responses
{ "messages": [ { "_id": { "$oid": "$oid" }, "conversation_id": "00000000-0000-0000-0000-000000000000", "external_id": "external_id", "direction": "inbound", "type": "text", "content": {}, "status": "pending", "sender_phone": "sender_phone", "sent_by_agent_id": "00000000-0000-0000-0000-000000000000", "sent_by_agent_name": "sent_by_agent_name", "reactions": [ { "emoji": "emoji", "agent_id": "00000000-0000-0000-0000-000000000000", "agent_name": "agent_name", "created_at": "2024-08-25T15:00:00Z" } ], "error_message": "error_message", "error_code": "error_code", "error_source": "error_source", "error_details": {}, "created_at": "2024-08-25T15:00:00Z" } ], "next_cursor": "next_cursor", "has_more": true }
json
application/json

Send an outbound message

POST
https://api-chat.misindo.id
/api/conversations/{id}/messages

Produces an outbound job to Kafka. The message-sender service delivers it via Meta Graph API (WhatsApp/Instagram) or SMTP (Email).

Send an outbound message › path Parameters

id
​string · uuid · required

Send an outbound message › Request Body

type
​string · enum · required

Mirrors MessageType in crates/omni-common/src/models/message.rs. contacts (a shared contact card) and postback (a tapped button) are emitted by the channel engines; unknown covers anything the parsers did not recognise.

Enum values:
text
image
document
template
audio
video
location
sticker
content
​required

Free-form JSON. For text: {"text": "Hello"} or {"body": "Hello"} — the WhatsApp sender reads text first and falls back to body. For image: {"url": "...", "caption": "..."}. Whichever key you send is stored verbatim and read back on Message.content, so sending body keeps writes and reads on the same key that every inbound message already uses.

Send an outbound message › Responses

200

Message created and queued for delivery

A stored message, as returned by `GET /api/conversations/{id}/messages` and by `POST /api/conversations/{id}/messages`. Mirrors `Message` in `crates/omni-common/src/models/message.rs`.
conversation_id
​string · uuid · required
direction
​string · enum · required
Enum values:
inbound
outbound
type
​string · enum · required

Mirrors MessageType in crates/omni-common/src/models/message.rs. contacts (a shared contact card) and postback (a tapped button) are emitted by the channel engines; unknown covers anything the parsers did not recognise.

Enum values:
text
image
document
template
audio
video
location
sticker
content
​required

Free-form JSON whose shape depends on type. READING a stored message: text lives under body. Every channel engine normalises inbound content to {"body": "..."} before storing it (see the parser modules in crates/chat-engine), and outbound text stored through this API arrives the same way from the first-party clients. The server's own reader, extract_content_text in crates/api-gateway/src/routes/messages/handlers.rs, tries body, then text, then caption, then subject — a consumer should do the same rather than reading one key. Email messages carry body, subject, html and text together. WRITING via SendMessageRequest: either key works. The WhatsApp sender reads text first and falls back to body (crates/message-sender/src/whatsapp.rs), and whichever you send is stored verbatim — so send body if you want reads and writes to agree.

status
​string · enum · required
Enum values:
pending
sent
delivered
read
failed
created_at
​string · date-time · required
​object

MongoDB ObjectId in extended JSON — {"$oid": "<24-hex>"}, NOT a bare string. The server field is a bson::oid::ObjectId, which serializes to this wrapper object under serde_json. Note the asymmetry with MessageSearchResult._id, which IS a plain hex string: the search handler flattens it with oid.to_hex() while building the result. The same logical value therefore arrives in two different shapes depending on the endpoint. MessageListResponse.next_cursor and the cursor query parameter both use the plain hex form, so the value read from here must be unwrapped before it can be used as a cursor. Absent on a message whose id was never assigned (the field is skipped when null).

external_id
​string
sender_phone
​string
sent_by_agent_id
​string · uuid

Agent who sent this outbound message. Absent on inbound and system-generated messages.

sent_by_agent_name
​string

Denormalized display name of the sending agent

​object[]

CRM-internal agent reactions. Never forwarded to the external channel. Absent when nobody has reacted.

error_message
​string

Why delivery failed — human-readable, only set when status is failed

error_code
​string

Provider error code for the failure (e.g. "132001" from Meta)

error_source
​string

Origin of the failure ("meta", "smtp", or "system")

error_details
​object

Raw provider error object (sanitized), for support/debugging

POST/api/conversations/{id}/messages
curl --request POST \ --url https://api-chat.misindo.id/api/conversations/:id/messages \ --header 'Content-Type: application/json' \ --data ' { "type": "text", "content": { "text": "Hello, how can I help you?" } } '
shell
Example Request Body
{ "type": "text", "content": { "text": "Hello, how can I help you?" } }
json
application/json
Example Responses
{ "_id": { "$oid": "$oid" }, "conversation_id": "00000000-0000-0000-0000-000000000000", "external_id": "external_id", "direction": "inbound", "type": "text", "content": {}, "status": "pending", "sender_phone": "sender_phone", "sent_by_agent_id": "00000000-0000-0000-0000-000000000000", "sent_by_agent_name": "sent_by_agent_name", "reactions": [ { "emoji": "emoji", "agent_id": "00000000-0000-0000-0000-000000000000", "agent_name": "agent_name", "created_at": "2024-08-25T15:00:00Z" } ], "error_message": "error_message", "error_code": "error_code", "error_source": "error_source", "error_details": {}, "created_at": "2024-08-25T15:00:00Z" }
json
application/json

Send a WhatsApp template message in one call

POST
https://api-chat.misindo.id
/api/messages/template

Send a business-initiated WhatsApp template to a phone number without an existing conversation_id. Auto-creates the contact and conversation, sends the template, and logs it under a campaign (shown as "Sent via API") with delivery tracking. Intended for third-party integrations.

Authenticate with X-API-Key (recommended) or a bearer JWT. Requires the campaigns.broadcast permission.

Send a WhatsApp template message in one call › Request Body

to
​string · required

Destination phone in international format, no +.

template
​string · required

Approved template name as registered with Meta.

language
​string

Template language code. Optional if the name is unambiguous.

integration_account_id
​string · uuid

WhatsApp account to send from. Defaults to the active default.

campaign_name
​string

Label shown in the broadcast history. Defaults to "API:

body_params
​string[]

Positional values for body variables {{1}}..{{N}}.

button_url_param
​string

Value substituted into a dynamic URL button's {{1}}.

​object[]

Escape hatch — raw Meta Cloud API components array. When present it is used verbatim and body_params/button_url_param are ignored.

Send a WhatsApp template message in one call › Responses

Template accepted and queued for delivery.

message_id
​string

MongoDB message id (hex).

conversation_id
​string · uuid
campaign_id
​string · uuid

Campaign this send is logged under.

status
​string
POST/api/messages/template
curl --request POST \ --url https://api-chat.misindo.id/api/messages/template \ --header 'Content-Type: application/json' \ --data ' { "to": "628172343210", "template": "send_invoice_customer_test", "language": "id", "body_params": [ "Bara", "9282920", "INV-001", "30-06-2026", "150.000" ] } '
shell
Example Request Body
{ "to": "628172343210", "template": "send_invoice_customer_test", "language": "id", "body_params": [ "Bara", "9282920", "INV-001", "30-06-2026", "150.000" ] }
json
application/json
Example Responses
{ "message_id": "message_id", "conversation_id": "00000000-0000-0000-0000-000000000000", "campaign_id": "00000000-0000-0000-0000-000000000000", "status": "sent" }
json
application/json

Search messages across conversations

GET
https://api-chat.misindo.id
/api/messages/search

Search messages across conversations › query Parameters

q
​string · required

Search query (text content). Trimmed; a blank query returns an empty page.

conversation_id
​string · uuid

Scope the search to a single conversation

channel
​string · enum
Enum values:
whatsapp
instagram
email
messenger
direction
​string · enum
Enum values:
inbound
outbound
from
​string · date-time

Start of a created-at range filter

to
​string · date-time

End of a created-at range filter

page
​integer · min: 1
Default: 1
per_page
​integer · min: 1 · max: 50
Default: 20

Search messages across conversations › Responses

200

Paginated search hits. Note this endpoint returns an envelope whose items are MessageSearchResult, NOT a bare array of Message.

​object[] · required
total
​integer · int64 · required
page
​integer · int64 · required
per_page
​integer · int64 · required

Page size actually applied, clamped to 50

total_pages
​integer · int64 · required
GET/api/messages/search
curl --request GET \ --url 'https://api-chat.misindo.id/api/messages/search?q=%3Cstring%3E'
shell
Example Responses
{ "results": [ { "_id": "_id", "conversation_id": "00000000-0000-0000-0000-000000000000", "direction": "inbound", "type": "text", "content": {}, "snippet": "snippet", "created_at": "2024-08-25T15:00:00Z", "contact_name": "contact_name", "contact_phone": "contact_phone", "channel": "channel" } ], "total": 0, "page": 0, "per_page": 0, "total_pages": 0 }
json
application/json

ConversationsContacts