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

Outgoing Webhooks

Endpoint

Outgoing webhook management (supervisor/admin only). Delivery is at-least-once: events are captured durably (Redis stream) and retried with exponential backoff, so the same event may be POSTed more than once (e.g. after a transient receiver/network failure or a dispatcher restart). Receivers must be idempotent — deduplicate on the event's natural identifiers in the JSON body (timestamp plus the relevant id under data, e.g. data.message.id / data.conversation_id) together with the X-Omnistream-Event header, and verify the X-Omnistream-Signature HMAC. Do not assume exactly-once. Deliveries that exhaust all retry attempts (default 8, capped exponential backoff) move to a dead-letter queue (status = dead_letter) and can be replayed. During a secret-rotation overlap window each delivery carries two signatures — X-Omnistream-Signature (new secret) and X-Omnistream-Signature-Previous (old secret); accept the delivery if EITHER header matches the secret you have stored. Full runbook: docs/webhook-reliability.md.


List outgoing webhooks

GET
https://api-chat.misindo.id
/api/outgoing-webhooks

Supervisor or admin only.

List outgoing webhooks › Responses

Outgoing webhooks

​object[]
id
​string · uuid · required
name
​string · required
url
​string · required
events
​required

JSON array of subscribed event type strings

is_active
​boolean · required
consecutive_failures
​integer · required
created_at
​string · date-time · required
updated_at
​string · date-time · required
secret
​string · writeOnly

HMAC signing secret. Write-only — never returned in responses. The staged rotation secret (secret_next) is likewise never returned; a pending rotation is only visible via secret_rotated_at.

secret_rotated_at
​string · date-time

When the current secret-rotation overlap window started. Null when no rotation is in progress (cleared on complete, cancel, or the 24-hour auto-promote).

created_by
​string · uuid
last_triggered_at
​string · date-time
last_success_at
​string · date-time
GET/api/outgoing-webhooks
curl --request GET \ --url https://api-chat.misindo.id/api/outgoing-webhooks
shell
Example Responses
[ { "id": "00000000-0000-0000-0000-000000000000", "name": "name", "url": "url", "secret": "secret", "secret_rotated_at": "2024-08-25T15:00:00Z", "events": {}, "is_active": true, "created_by": "00000000-0000-0000-0000-000000000000", "last_triggered_at": "2024-08-25T15:00:00Z", "last_success_at": "2024-08-25T15:00:00Z", "consecutive_failures": 0, "created_at": "2024-08-25T15:00:00Z", "updated_at": "2024-08-25T15:00:00Z" } ]
json
application/json

Create an outgoing webhook

POST
https://api-chat.misindo.id
/api/outgoing-webhooks

Supervisor or admin only.

Create an outgoing webhook › Request Body

name
​string · minLength: 1 · required
url
​string · required

Must start with http:// or https://

secret
​string
events
​string[]

Valid types: message.received, message.sent, message.status, conversation.created, conversation.resolved, conversation.assigned, contact.created

Create an outgoing webhook › Responses

Webhook created

id
​string · uuid · required
name
​string · required
url
​string · required
events
​required

JSON array of subscribed event type strings

is_active
​boolean · required
consecutive_failures
​integer · required
created_at
​string · date-time · required
updated_at
​string · date-time · required
secret
​string · writeOnly

HMAC signing secret. Write-only — never returned in responses. The staged rotation secret (secret_next) is likewise never returned; a pending rotation is only visible via secret_rotated_at.

secret_rotated_at
​string · date-time

When the current secret-rotation overlap window started. Null when no rotation is in progress (cleared on complete, cancel, or the 24-hour auto-promote).

created_by
​string · uuid
last_triggered_at
​string · date-time
last_success_at
​string · date-time
POST/api/outgoing-webhooks
curl --request POST \ --url https://api-chat.misindo.id/api/outgoing-webhooks \ --header 'Content-Type: application/json' \ --data ' { "name": "name", "url": "url", "secret": "secret", "events": [ "string" ] } '
shell
Example Request Body
{ "name": "name", "url": "url", "secret": "secret", "events": [ "string" ] }
json
Example Responses
{ "id": "00000000-0000-0000-0000-000000000000", "name": "name", "url": "url", "secret": "secret", "secret_rotated_at": "2024-08-25T15:00:00Z", "events": {}, "is_active": true, "created_by": "00000000-0000-0000-0000-000000000000", "last_triggered_at": "2024-08-25T15:00:00Z", "last_success_at": "2024-08-25T15:00:00Z", "consecutive_failures": 0, "created_at": "2024-08-25T15:00:00Z", "updated_at": "2024-08-25T15:00:00Z" }
json
application/json

List available webhook event types

GET
https://api-chat.misindo.id
/api/outgoing-webhooks/events

Supervisor or admin only.

List available webhook event types › Responses

200

Event type strings

​string[]
GET/api/outgoing-webhooks/events
curl --request GET \ --url https://api-chat.misindo.id/api/outgoing-webhooks/events
shell
Example Responses
[ "string" ]
json
application/json

Aggregated delivery statistics

GET
https://api-chat.misindo.id
/api/outgoing-webhooks/deliveries/stats

Supervisor or admin only. Per-status delivery counts (including dead-lettered rows) plus average response time, over an optional created_at date range.

Aggregated delivery statistics › query Parameters

from
​string · date-time
to
​string · date-time

Aggregated delivery statistics › Responses

Delivery statistics

total
​integer · required
success
​integer · required
failed
​integer · required

Failed but still retryable (attempt < max_attempts)

pending
​integer · required
dead_letter
​integer · required

Terminally failed deliveries awaiting replay or 30-day cleanup

avg_response_time_ms
​number

Average milliseconds between created_at and completed_at

GET/api/outgoing-webhooks/deliveries/stats
curl --request GET \ --url https://api-chat.misindo.id/api/outgoing-webhooks/deliveries/stats
shell
Example Responses
{ "total": 0, "success": 0, "failed": 0, "pending": 0, "dead_letter": 0, "avg_response_time_ms": 0 }
json
application/json

Bulk-replay deliveries by id

POST
https://api-chat.misindo.id
/api/outgoing-webhooks/deliveries/replay

Supervisor or admin only. Resets each failed/dead-lettered delivery in place — status back to pending, attempt counter zeroed, response fields cleared — so the scheduler re-sends it with the original payload. Ids that are unknown or not replayable are skipped and excluded from replayed.

Bulk-replay deliveries by id › Request Body

delivery_ids
​string[] · minItems: 1 · maxItems: 500 · required

Deliveries to replay; only failed/dead_letter rows are reset

Bulk-replay deliveries by id › Responses

Replay summary

replayed
​integer

Rows actually reset to pending

requested
​integer

Ids received in the request

POST/api/outgoing-webhooks/deliveries/replay
curl --request POST \ --url https://api-chat.misindo.id/api/outgoing-webhooks/deliveries/replay \ --header 'Content-Type: application/json' \ --data ' { "delivery_ids": [ "00000000-0000-0000-0000-000000000000" ] } '
shell
Example Request Body
{ "delivery_ids": [ "00000000-0000-0000-0000-000000000000" ] }
json
Example Responses
{ "replayed": 0, "requested": 0 }
json
application/json

Replay all dead-lettered deliveries

POST
https://api-chat.misindo.id
/api/outgoing-webhooks/deliveries/replay-failed

Supervisor or admin only. Resets every dead_letter delivery in place for re-sending. The body is optional — omit it (or send {}) to replay across all webhooks, or pass webhook_id to scope the replay to a single webhook.

Replay all dead-lettered deliveries › Request Body optional

webhook_id
​string · uuid

Restrict the replay to this webhook's deliveries

Replay all dead-lettered deliveries › Responses

Replay summary

replayed
​integer
POST/api/outgoing-webhooks/deliveries/replay-failed
curl --request POST \ --url https://api-chat.misindo.id/api/outgoing-webhooks/deliveries/replay-failed \ --header 'Content-Type: application/json' \ --data ' { "webhook_id": "00000000-0000-0000-0000-000000000000" } '
shell
Example Request Body
{ "webhook_id": "00000000-0000-0000-0000-000000000000" }
json
Example Responses
{ "replayed": 0 }
json
application/json

Replay a single delivery

POST
https://api-chat.misindo.id
/api/outgoing-webhooks/deliveries/{delivery_id}/replay

Supervisor or admin only. Resets one failed or dead-lettered delivery in place (status back to pending, attempt counter zeroed, response fields cleared); the scheduler re-sends it with the original payload within ~30 seconds.

Replay a single delivery › path Parameters

delivery_id
​string · uuid · required

Replay a single delivery › Responses

Delivery queued for replay

delivery_id
​string · uuid · required
status
​string · required

Always "queued" on success

message
​string · required
POST/api/outgoing-webhooks/deliveries/{delivery_id}/replay
curl --request POST \ --url https://api-chat.misindo.id/api/outgoing-webhooks/deliveries/:delivery_id/replay
shell
Example Responses
{ "delivery_id": "00000000-0000-0000-0000-000000000000", "status": "status", "message": "message" }
json
application/json

Delete an outgoing webhook

DELETE
https://api-chat.misindo.id
/api/outgoing-webhooks/{id}

Supervisor or admin only.

Delete an outgoing webhook › path Parameters

id
​string · uuid · required

Delete an outgoing webhook › Responses

Webhook deleted

message
​string
id
​string · uuid
DELETE/api/outgoing-webhooks/{id}
curl --request DELETE \ --url https://api-chat.misindo.id/api/outgoing-webhooks/:id
shell
Example Responses
{ "message": "message", "id": "00000000-0000-0000-0000-000000000000" }
json
application/json

Update an outgoing webhook

PATCH
https://api-chat.misindo.id
/api/outgoing-webhooks/{id}

Supervisor or admin only.

Update an outgoing webhook › path Parameters

id
​string · uuid · required

Update an outgoing webhook › Request Body

name
​string
url
​string
secret
​string
events
​string[]
is_active
​boolean

Update an outgoing webhook › Responses

Webhook updated

id
​string · uuid · required
name
​string · required
url
​string · required
events
​required

JSON array of subscribed event type strings

is_active
​boolean · required
consecutive_failures
​integer · required
created_at
​string · date-time · required
updated_at
​string · date-time · required
secret
​string · writeOnly

HMAC signing secret. Write-only — never returned in responses. The staged rotation secret (secret_next) is likewise never returned; a pending rotation is only visible via secret_rotated_at.

secret_rotated_at
​string · date-time

When the current secret-rotation overlap window started. Null when no rotation is in progress (cleared on complete, cancel, or the 24-hour auto-promote).

created_by
​string · uuid
last_triggered_at
​string · date-time
last_success_at
​string · date-time
PATCH/api/outgoing-webhooks/{id}
curl --request PATCH \ --url https://api-chat.misindo.id/api/outgoing-webhooks/:id \ --header 'Content-Type: application/json' \ --data ' { "name": "name", "url": "url", "secret": "secret", "events": [ "string" ], "is_active": true } '
shell
Example Request Body
{ "name": "name", "url": "url", "secret": "secret", "events": [ "string" ], "is_active": true }
json
Example Responses
{ "id": "00000000-0000-0000-0000-000000000000", "name": "name", "url": "url", "secret": "secret", "secret_rotated_at": "2024-08-25T15:00:00Z", "events": {}, "is_active": true, "created_by": "00000000-0000-0000-0000-000000000000", "last_triggered_at": "2024-08-25T15:00:00Z", "last_success_at": "2024-08-25T15:00:00Z", "consecutive_failures": 0, "created_at": "2024-08-25T15:00:00Z", "updated_at": "2024-08-25T15:00:00Z" }
json
application/json

List deliveries for a webhook

GET
https://api-chat.misindo.id
/api/outgoing-webhooks/{id}/deliveries

Supervisor or admin only. Paginated, newest first.

List deliveries for a webhook › path Parameters

id
​string · uuid · required

List deliveries for a webhook › query Parameters

page
​integer
Default: 1
per_page
​integer · max: 100
Default: 50

List deliveries for a webhook › Responses

200

Webhook deliveries

​object[]
id
​string · uuid · required
webhook_id
​string · uuid · required
event_type
​string · required
payload
​required
status
​string · enum · required

pending = queued, awaiting the next scheduler tick; sending = claimed by a dispatcher worker (15-minute lease, reclaimed if the lease expires); success = delivered (HTTP 2xx); failed = last attempt failed but retries remain; dead_letter = terminal (attempts exhausted, webhook missing/inactive, or URL blocked) — never retried automatically, only a replay re-queues it.

Enum values:
pending
sending
success
failed
dead_letter
attempt
​integer · required
max_attempts
​integer · required

Delivery attempts before dead-lettering (default 8)

created_at
​string · date-time · required
http_status
​integer
response_body
​string
error_message
​string
next_retry_at
​string · date-time
completed_at
​string · date-time
GET/api/outgoing-webhooks/{id}/deliveries
curl --request GET \ --url https://api-chat.misindo.id/api/outgoing-webhooks/:id/deliveries
shell
Example Responses
[ { "id": "00000000-0000-0000-0000-000000000000", "webhook_id": "00000000-0000-0000-0000-000000000000", "event_type": "event_type", "payload": {}, "status": "pending", "http_status": 0, "response_body": "response_body", "error_message": "error_message", "attempt": 0, "max_attempts": 0, "next_retry_at": "2024-08-25T15:00:00Z", "created_at": "2024-08-25T15:00:00Z", "completed_at": "2024-08-25T15:00:00Z" } ]
json
application/json

Send a test event to the webhook

POST
https://api-chat.misindo.id
/api/outgoing-webhooks/{id}/test

Supervisor or admin only. Sends a test payload and returns the response.

Send a test event to the webhook › path Parameters

id
​string · uuid · required

Send a test event to the webhook › Responses

Test result

success
​boolean
http_status
​integer
response_body
​string
error
​string
POST/api/outgoing-webhooks/{id}/test
curl --request POST \ --url https://api-chat.misindo.id/api/outgoing-webhooks/:id/test
shell
Example Responses
{ "success": true, "http_status": 0, "response_body": "response_body", "error": "error" }
json
application/json

Start a signing-secret rotation

POST
https://api-chat.misindo.id
/api/outgoing-webhooks/{id}/rotate-secret

Supervisor or admin only. Stages a new HMAC secret and opens a 24-hour overlap window: deliveries are signed with the NEW secret in X-Omnistream-Signature and with the OLD secret in X-Omnistream-Signature-Previous, so receivers can switch secrets without dropping deliveries. Complete (or cancel) the rotation explicitly, or it auto-promotes after 24 hours. The new secret is returned once in this response and never again.

Start a signing-secret rotation › path Parameters

id
​string · uuid · required

Start a signing-secret rotation › Request Body optional

secret
​string · minLength: 16 · maxLength: 255

Optional custom secret (16–255 chars after trimming). Omit to have the server generate a 64-character lowercase-hex secret.

Start a signing-secret rotation › Responses

Rotation started

id
​string · uuid · required
secret
​string · required

The new signing secret — shown once, never returned again

rotated_at
​string · date-time · required

Start of the dual-signature overlap window

overlap
​string · required

Human-readable note that the previous secret keeps working for up to 24 hours or until the rotation is completed

POST/api/outgoing-webhooks/{id}/rotate-secret
curl --request POST \ --url https://api-chat.misindo.id/api/outgoing-webhooks/:id/rotate-secret \ --header 'Content-Type: application/json' \ --data ' { "secret": "secretaaaaaaaaaa" } '
shell
Example Request Body
{ "secret": "secretaaaaaaaaaa" }
json
Example Responses
{ "id": "00000000-0000-0000-0000-000000000000", "secret": "secret", "rotated_at": "2024-08-25T15:00:00Z", "overlap": "overlap" }
json
application/json

Complete a pending secret rotation

POST
https://api-chat.misindo.id
/api/outgoing-webhooks/{id}/rotate-secret/complete

Supervisor or admin only. Promotes the staged secret to the active signing secret and ends the overlap window — the old secret stops matching immediately.

Complete a pending secret rotation › path Parameters

id
​string · uuid · required

Complete a pending secret rotation › Responses

Rotation completed

id
​string · uuid · required
name
​string · required
url
​string · required
events
​required

JSON array of subscribed event type strings

is_active
​boolean · required
consecutive_failures
​integer · required
created_at
​string · date-time · required
updated_at
​string · date-time · required
secret
​string · writeOnly

HMAC signing secret. Write-only — never returned in responses. The staged rotation secret (secret_next) is likewise never returned; a pending rotation is only visible via secret_rotated_at.

secret_rotated_at
​string · date-time

When the current secret-rotation overlap window started. Null when no rotation is in progress (cleared on complete, cancel, or the 24-hour auto-promote).

created_by
​string · uuid
last_triggered_at
​string · date-time
last_success_at
​string · date-time
POST/api/outgoing-webhooks/{id}/rotate-secret/complete
curl --request POST \ --url https://api-chat.misindo.id/api/outgoing-webhooks/:id/rotate-secret/complete
shell
Example Responses
{ "id": "00000000-0000-0000-0000-000000000000", "name": "name", "url": "url", "secret": "secret", "secret_rotated_at": "2024-08-25T15:00:00Z", "events": {}, "is_active": true, "created_by": "00000000-0000-0000-0000-000000000000", "last_triggered_at": "2024-08-25T15:00:00Z", "last_success_at": "2024-08-25T15:00:00Z", "consecutive_failures": 0, "created_at": "2024-08-25T15:00:00Z", "updated_at": "2024-08-25T15:00:00Z" }
json
application/json

Cancel a pending secret rotation

POST
https://api-chat.misindo.id
/api/outgoing-webhooks/{id}/rotate-secret/cancel

Supervisor or admin only. Discards the staged secret and keeps the OLD secret active; deliveries return to a single X-Omnistream-Signature header.

Cancel a pending secret rotation › path Parameters

id
​string · uuid · required

Cancel a pending secret rotation › Responses

Rotation cancelled

id
​string · uuid · required
name
​string · required
url
​string · required
events
​required

JSON array of subscribed event type strings

is_active
​boolean · required
consecutive_failures
​integer · required
created_at
​string · date-time · required
updated_at
​string · date-time · required
secret
​string · writeOnly

HMAC signing secret. Write-only — never returned in responses. The staged rotation secret (secret_next) is likewise never returned; a pending rotation is only visible via secret_rotated_at.

secret_rotated_at
​string · date-time

When the current secret-rotation overlap window started. Null when no rotation is in progress (cleared on complete, cancel, or the 24-hour auto-promote).

created_by
​string · uuid
last_triggered_at
​string · date-time
last_success_at
​string · date-time
POST/api/outgoing-webhooks/{id}/rotate-secret/cancel
curl --request POST \ --url https://api-chat.misindo.id/api/outgoing-webhooks/:id/rotate-secret/cancel
shell
Example Responses
{ "id": "00000000-0000-0000-0000-000000000000", "name": "name", "url": "url", "secret": "secret", "secret_rotated_at": "2024-08-25T15:00:00Z", "events": {}, "is_active": true, "created_by": "00000000-0000-0000-0000-000000000000", "last_triggered_at": "2024-08-25T15:00:00Z", "last_success_at": "2024-08-25T15:00:00Z", "consecutive_failures": 0, "created_at": "2024-08-25T15:00:00Z", "updated_at": "2024-08-25T15:00:00Z" }
json
application/json

ContactsWA Templates