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

Auth

Endpoint

Authentication (login, logout, session)


Login with email and password

POST
https://api-chat.misindo.id
/api/auth/login

Returns a JWT token in both the response body and an httpOnly access_token cookie.

Login with email and password › Request Body

email
​string · email · required
password
​string · minLength: 1 · required
totp_code
​string

TOTP authenticator code, when completing a TOTP-2FA login.

email_code
​string

The emailed OTP, when completing an email-2FA login.

request_email_code
​boolean

When true, ask the server to email an OTP instead of verifying a code on this request.

turnstile_token
​string

Cloudflare Turnstile token, when the CAPTCHA widget is enabled.

remember_me
​boolean

When true, issue a longer-lived "remember me" session (7 days, cookie Max-Age and JWT exp) instead of the default TTL. Only takes effect after 2FA succeeds; ignored on 2FA-challenge responses.

Login with email and password › Responses

Login successful

token
​string · required

JWT token

​object · required
POST/api/auth/login
curl --request POST \ --url https://api-chat.misindo.id/api/auth/login \ --header 'Content-Type: application/json' \ --data ' { "email": "test@example.com", "password": "password", "totp_code": "totp_code", "email_code": "email_code", "request_email_code": true, "turnstile_token": "turnstile_token", "remember_me": true } '
shell
Example Request Body
{ "email": "test@example.com", "password": "password", "totp_code": "totp_code", "email_code": "email_code", "request_email_code": true, "turnstile_token": "turnstile_token", "remember_me": true }
json
Example Responses
{ "token": "token", "agent": { "id": "00000000-0000-0000-0000-000000000000", "email": "test@example.com", "full_name": "full_name", "role": "admin", "is_online": true } }
json
application/json

Request a password-reset code (agent)

POST
https://api-chat.misindo.id
/api/auth/forgot-password

Always returns a generic success regardless of whether the email is registered (enumeration-safe). When it is, a 6-digit reset code is emailed (10-minute TTL, 60s resend cooldown).

Request a password-reset code (agent) › Request Body

email
​string · email · required
turnstile_token
​string

Required when the Turnstile widget is enabled.

Request a password-reset code (agent) › Responses

200

Generic acknowledgement (no enumeration).

No data returned
POST/api/auth/forgot-password
curl --request POST \ --url https://api-chat.misindo.id/api/auth/forgot-password \ --header 'Content-Type: application/json' \ --data ' { "email": "test@example.com", "turnstile_token": "turnstile_token" } '
shell
Example Request Body
{ "email": "test@example.com", "turnstile_token": "turnstile_token" }
json
Example Responses
No example specified for this content type

Set a new password with a reset code (agent)

POST
https://api-chat.misindo.id
/api/auth/reset-password

Verifies the emailed 6-digit code and sets a new password (min 8 chars). Unknown email and wrong/expired code return the same generic 422. On success all existing sessions are revoked.

Set a new password with a reset code (agent) › Request Body

email
​string · email · required
code
​string · required

The 6-digit reset code.

new_password
​string · minLength: 8 · required
turnstile_token
​string

Set a new password with a reset code (agent) › Responses

Password updated; sign in again.

No data returned
POST/api/auth/reset-password
curl --request POST \ --url https://api-chat.misindo.id/api/auth/reset-password \ --header 'Content-Type: application/json' \ --data ' { "email": "test@example.com", "code": "code", "new_password": "new_password", "turnstile_token": "turnstile_token" } '
shell
Example Request Body
{ "email": "test@example.com", "code": "code", "new_password": "new_password", "turnstile_token": "turnstile_token" }
json
Example Responses
No example specified for this content type

Get current agent profile

GET
https://api-chat.misindo.id
/api/auth/me

Get current agent profile › Responses

Current agent

id
​string · uuid · required
email
​string · email · required
full_name
​string · required
role
​string · enum · required
Enum values:
admin
supervisor
agent
is_online
​boolean · required
GET/api/auth/me
curl --request GET \ --url https://api-chat.misindo.id/api/auth/me
shell
Example Responses
{ "id": "00000000-0000-0000-0000-000000000000", "email": "test@example.com", "full_name": "full_name", "role": "admin", "is_online": true }
json
application/json

Logout (clears cookie)

POST
https://api-chat.misindo.id
/api/auth/logout

Logout (clears cookie) › Responses

200

Logged out

No data returned
POST/api/auth/logout
curl --request POST \ --url https://api-chat.misindo.id/api/auth/logout
shell
Example Responses
No example specified for this content type

Advertise available SSO login methods

GET
https://api-chat.misindo.id
/api/auth/sso/options

Advertise available SSO login methods › Responses

200

Which SSO login methods this deployment offers

google_enabled
​boolean · required

True when platform-level Google SSO login is configured.

GET/api/auth/sso/options
curl --request GET \ --url https://api-chat.misindo.id/api/auth/sso/options
shell
Example Responses
{ "google_enabled": true }
json
application/json

Begin Google SSO login

GET
https://api-chat.misindo.id
/api/auth/sso/google/start

Redirects the browser to Google's authorization endpoint and sets the short-lived sso_flow state cookie (login-CSRF guard). When Google SSO is not configured, rate limited, or the provider errors, it instead 302-redirects to the frontend login page with an sso_error query code (e.g. not_configured, rate_limited).

Begin Google SSO login › Responses

Redirect to the IdP authorization URL, or to the frontend login page with sso_error when the flow cannot start.

No data returned
GET/api/auth/sso/google/start
curl --request GET \ --url https://api-chat.misindo.id/api/auth/sso/google/start
shell
Example Responses
No example specified for this content type

Google SSO callback (OIDC redirect URI)

GET
https://api-chat.misindo.id
/api/auth/sso/google/callback

Completes the Google OIDC code exchange. The state query param must equal the sso_flow cookie. On success, 302-redirects to the frontend (/login?sso=ok) with the access_token session cookie set; on failure, 302-redirects to the frontend login page with an sso_error query code.

Google SSO callback (OIDC redirect URI) › query Parameters

code
​string

Authorization code from the IdP.

state
​string

CSRF state issued at /start; must equal the sso_flow cookie.

error
​string

Present when the user cancels at the IdP (e.g. access_denied).

Google SSO callback (OIDC redirect URI) › Responses

Redirect to the frontend (session cookie set on success only)

No data returned
GET/api/auth/sso/google/callback
curl --request GET \ --url https://api-chat.misindo.id/api/auth/sso/google/callback
shell
Example Responses
No example specified for this content type

Discover company SSO availability for an email

POST
https://api-chat.misindo.id
/api/auth/sso/discover

Checks whether an enabled company SSO provider accepts the email's domain. Reveals availability only — never a tenant name or issuer (enumeration-safe). When available, returns a relative start_url carrying a single-use ticket.

Discover company SSO availability for an email › Request Body

email
​string · email · required
turnstile_token
​string

Cloudflare Turnstile token, when the CAPTCHA widget is enabled.

Discover company SSO availability for an email › Responses

200

Discovery result

sso_available
​boolean · required

True when an enabled company SSO provider accepts the email's domain.

start_url
​string · required

Relative URL that begins the company SSO flow (carries a single-use ticket). Null when no provider matches.

POST/api/auth/sso/discover
curl --request POST \ --url https://api-chat.misindo.id/api/auth/sso/discover \ --header 'Content-Type: application/json' \ --data ' { "email": "test@example.com", "turnstile_token": "turnstile_token" } '
shell
Example Request Body
{ "email": "test@example.com", "turnstile_token": "turnstile_token" }
json
Example Responses
{ "sso_available": true, "start_url": "start_url" }
json
application/json

Begin company SSO login (ticket from /discover)

GET
https://api-chat.misindo.id
/api/auth/sso/company/start

Begin company SSO login (ticket from /discover) › query Parameters

ticket
​string · uuid · required

Single-use ticket minted by POST /api/auth/sso/discover.

Begin company SSO login (ticket from /discover) › Responses

Redirect to the company IdP authorization URL, or to the frontend login page with sso_error for an invalid/expired ticket.

No data returned
GET/api/auth/sso/company/start
curl --request GET \ --url 'https://api-chat.misindo.id/api/auth/sso/company/start?ticket=%3Cstring%3E'
shell
Example Responses
No example specified for this content type

Company SSO callback (OIDC redirect URI)

GET
https://api-chat.misindo.id
/api/auth/sso/company/callback

Completes the company OIDC code exchange. Same contract as the Google callback — state must equal the sso_flow cookie; success sets the session cookie and 302-redirects to the frontend, failure redirects with an sso_error query code.

Company SSO callback (OIDC redirect URI) › query Parameters

code
​string

Authorization code from the IdP.

state
​string

CSRF state issued at /start; must equal the sso_flow cookie.

error
​string

Present when the user cancels at the IdP (e.g. access_denied).

Company SSO callback (OIDC redirect URI) › Responses

Redirect to the frontend (session cookie set on success only)

No data returned
GET/api/auth/sso/company/callback
curl --request GET \ --url https://api-chat.misindo.id/api/auth/sso/company/callback
shell
Example Responses
No example specified for this content type

Begin a passkey (WebAuthn) login ceremony

POST
https://api-chat.misindo.id
/api/auth/passkeys/login/options

Begin a passkey (WebAuthn) login ceremony › Request Body

turnstile_token
​string

Cloudflare Turnstile token, when the CAPTCHA widget is enabled.

Begin a passkey (WebAuthn) login ceremony › Responses

200

WebAuthn request options for navigator.credentials.get

challenge_id
​string · uuid · required

Server-side ceremony id; echo it back on the matching verify call.

options
​object · required

WebAuthn options to pass to the browser (navigator.credentials.create for registration, navigator.credentials.get for login).

POST/api/auth/passkeys/login/options
curl --request POST \ --url https://api-chat.misindo.id/api/auth/passkeys/login/options \ --header 'Content-Type: application/json' \ --data ' { "turnstile_token": "turnstile_token" } '
shell
Example Request Body
{ "turnstile_token": "turnstile_token" }
json
Example Responses
{ "challenge_id": "00000000-0000-0000-0000-000000000000", "options": {} }
json
application/json

Complete a passkey login

POST
https://api-chat.misindo.id
/api/auth/passkeys/login/verify

Verifies the WebAuthn assertion (user verification required) and, on success, issues a session exactly like /api/auth/login. All failure modes return the same generic 401.

Complete a passkey login › Request Body

challenge_id
​string · uuid · required

The id returned by /api/auth/passkeys/login/options.

credential
​object · required

The PublicKeyCredential assertion from navigator.credentials.get.

Complete a passkey login › Responses

Login successful

token
​string · required

JWT token

​object · required
POST/api/auth/passkeys/login/verify
curl --request POST \ --url https://api-chat.misindo.id/api/auth/passkeys/login/verify \ --header 'Content-Type: application/json' \ --data ' { "challenge_id": "00000000-0000-0000-0000-000000000000", "credential": {} } '
shell
Example Request Body
{ "challenge_id": "00000000-0000-0000-0000-000000000000", "credential": {} }
json
Example Responses
{ "token": "token", "agent": { "id": "00000000-0000-0000-0000-000000000000", "email": "test@example.com", "full_name": "full_name", "role": "admin", "is_online": true } }
json
application/json

Begin passkey registration for the current agent

POST
https://api-chat.misindo.id
/api/auth/passkeys/register/options

Requires an authenticated session. Forces a discoverable (resident) credential with user verification; credentials already registered by this agent are excluded so a device cannot double-enroll.

Begin passkey registration for the current agent › Responses

200

WebAuthn creation options for navigator.credentials.create

challenge_id
​string · uuid · required

Server-side ceremony id; echo it back on the matching verify call.

options
​object · required

WebAuthn options to pass to the browser (navigator.credentials.create for registration, navigator.credentials.get for login).

POST/api/auth/passkeys/register/options
curl --request POST \ --url https://api-chat.misindo.id/api/auth/passkeys/register/options
shell
Example Responses
{ "challenge_id": "00000000-0000-0000-0000-000000000000", "options": {} }
json
application/json

Complete passkey registration

POST
https://api-chat.misindo.id
/api/auth/passkeys/register/verify

Complete passkey registration › Request Body

challenge_id
​string · uuid · required

The id returned by /api/auth/passkeys/register/options.

credential
​object · required

The RegisterPublicKeyCredential from navigator.credentials.create.

device_label
​string

Optional friendly device name shown in the passkey list.

Complete passkey registration › Responses

200

Passkey stored

id
​string · uuid · required
created_at
​string · date-time · required
device_label
​string

Friendly device name shown in the passkey list.

last_used_at
​string · date-time
POST/api/auth/passkeys/register/verify
curl --request POST \ --url https://api-chat.misindo.id/api/auth/passkeys/register/verify \ --header 'Content-Type: application/json' \ --data ' { "challenge_id": "00000000-0000-0000-0000-000000000000", "credential": {}, "device_label": "device_label" } '
shell
Example Request Body
{ "challenge_id": "00000000-0000-0000-0000-000000000000", "credential": {}, "device_label": "device_label" }
json
Example Responses
{ "id": "00000000-0000-0000-0000-000000000000", "device_label": "device_label", "created_at": "2024-08-25T15:00:00Z", "last_used_at": "2024-08-25T15:00:00Z" }
json
application/json

List the current agent's passkeys

GET
https://api-chat.misindo.id
/api/auth/passkeys

List the current agent's passkeys › Responses

200

Passkeys (metadata only — never key material)

​object[]
id
​string · uuid · required
created_at
​string · date-time · required
device_label
​string

Friendly device name shown in the passkey list.

last_used_at
​string · date-time
GET/api/auth/passkeys
curl --request GET \ --url https://api-chat.misindo.id/api/auth/passkeys
shell
Example Responses
[ { "id": "00000000-0000-0000-0000-000000000000", "device_label": "device_label", "created_at": "2024-08-25T15:00:00Z", "last_used_at": "2024-08-25T15:00:00Z" } ]
json
application/json

Delete one of the current agent's passkeys

DELETE
https://api-chat.misindo.id
/api/auth/passkeys/{id}

Delete one of the current agent's passkeys › path Parameters

id
​string · uuid · required

Delete one of the current agent's passkeys › Responses

Passkey removed

message
​string
DELETE/api/auth/passkeys/{id}
curl --request DELETE \ --url https://api-chat.misindo.id/api/auth/passkeys/:id
shell
Example Responses
{ "message": "message" }
json
application/json

List company SSO providers

GET
https://api-chat.misindo.id
/api/settings/sso-providers

Requires the admin-only sso.manage permission. Client secrets are never returned — only the has_client_secret flag.

List company SSO providers › Responses

Configured SSO providers

​object[]
id
​string · uuid · required
provider_name
​string · required
issuer_url
​string · required
client_id
​string · required
has_client_secret
​boolean · required

True when a client secret is stored. The secret itself is never returned.

allowed_email_domains
​string[] · required
enabled
​boolean · required
require_email_verified
​boolean · required
created_at
​string · date-time · required
updated_at
​string · date-time · required
GET/api/settings/sso-providers
curl --request GET \ --url https://api-chat.misindo.id/api/settings/sso-providers
shell
Example Responses
[ { "id": "00000000-0000-0000-0000-000000000000", "provider_name": "provider_name", "issuer_url": "issuer_url", "client_id": "client_id", "has_client_secret": true, "allowed_email_domains": [ "string" ], "enabled": true, "require_email_verified": true, "created_at": "2024-08-25T15:00:00Z", "updated_at": "2024-08-25T15:00:00Z" } ]
json
application/json

Create a company SSO provider

POST
https://api-chat.misindo.id
/api/settings/sso-providers

Requires the admin-only sso.manage permission. The issuer URL is validated and at least one allowed email domain is required.

Create a company SSO provider › Request Body

provider_name
​string · required
issuer_url
​string · required

OIDC issuer base URL (must serve an OIDC discovery document).

client_id
​string · required
client_secret
​string · required

Stored encrypted at rest; never returned by the API.

allowed_email_domains
​string[] · minItems: 1 · required
enabled
​boolean
Default: true
require_email_verified
​boolean
Default: true

Create a company SSO provider › Responses

Provider created

id
​string · uuid · required
provider_name
​string · required
issuer_url
​string · required
client_id
​string · required
has_client_secret
​boolean · required

True when a client secret is stored. The secret itself is never returned.

allowed_email_domains
​string[] · required
enabled
​boolean · required
require_email_verified
​boolean · required
created_at
​string · date-time · required
updated_at
​string · date-time · required
POST/api/settings/sso-providers
curl --request POST \ --url https://api-chat.misindo.id/api/settings/sso-providers \ --header 'Content-Type: application/json' \ --data ' { "provider_name": "provider_name", "issuer_url": "issuer_url", "client_id": "client_id", "client_secret": "client_secret", "allowed_email_domains": [ "string" ], "enabled": true, "require_email_verified": true } '
shell
Example Request Body
{ "provider_name": "provider_name", "issuer_url": "issuer_url", "client_id": "client_id", "client_secret": "client_secret", "allowed_email_domains": [ "string" ], "enabled": true, "require_email_verified": true }
json
Example Responses
{ "id": "00000000-0000-0000-0000-000000000000", "provider_name": "provider_name", "issuer_url": "issuer_url", "client_id": "client_id", "has_client_secret": true, "allowed_email_domains": [ "string" ], "enabled": true, "require_email_verified": true, "created_at": "2024-08-25T15:00:00Z", "updated_at": "2024-08-25T15:00:00Z" }
json
application/json

Update a company SSO provider

PUT
https://api-chat.misindo.id
/api/settings/sso-providers/{id}

Requires the admin-only sso.manage permission. All fields optional; an omitted or empty client_secret keeps the stored one.

Update a company SSO provider › path Parameters

id
​string · uuid · required

Update a company SSO provider › Request Body

All fields optional; an omitted or empty `client_secret` keeps the stored one (so the masked value can be round-tripped from the UI).
provider_name
​string
issuer_url
​string
client_id
​string
client_secret
​string
allowed_email_domains
​string[]
enabled
​boolean
require_email_verified
​boolean

Update a company SSO provider › Responses

Updated provider

id
​string · uuid · required
provider_name
​string · required
issuer_url
​string · required
client_id
​string · required
has_client_secret
​boolean · required

True when a client secret is stored. The secret itself is never returned.

allowed_email_domains
​string[] · required
enabled
​boolean · required
require_email_verified
​boolean · required
created_at
​string · date-time · required
updated_at
​string · date-time · required
PUT/api/settings/sso-providers/{id}
curl --request PUT \ --url https://api-chat.misindo.id/api/settings/sso-providers/:id \ --header 'Content-Type: application/json' \ --data ' { "provider_name": "provider_name", "issuer_url": "issuer_url", "client_id": "client_id", "client_secret": "client_secret", "allowed_email_domains": [ "string" ], "enabled": true, "require_email_verified": true } '
shell
Example Request Body
{ "provider_name": "provider_name", "issuer_url": "issuer_url", "client_id": "client_id", "client_secret": "client_secret", "allowed_email_domains": [ "string" ], "enabled": true, "require_email_verified": true }
json
Example Responses
{ "id": "00000000-0000-0000-0000-000000000000", "provider_name": "provider_name", "issuer_url": "issuer_url", "client_id": "client_id", "has_client_secret": true, "allowed_email_domains": [ "string" ], "enabled": true, "require_email_verified": true, "created_at": "2024-08-25T15:00:00Z", "updated_at": "2024-08-25T15:00:00Z" }
json
application/json

Delete a company SSO provider

DELETE
https://api-chat.misindo.id
/api/settings/sso-providers/{id}

Requires the admin-only sso.manage permission.

Delete a company SSO provider › path Parameters

id
​string · uuid · required

Delete a company SSO provider › Responses

Provider deleted

message
​string
DELETE/api/settings/sso-providers/{id}
curl --request DELETE \ --url https://api-chat.misindo.id/api/settings/sso-providers/:id
shell
Example Responses
{ "message": "message" }
json
application/json

Issue a fresh JWT for the current session

GET
https://api-chat.misindo.id
/api/auth/token

Used by the frontend to obtain a WS token after page reload when the httpOnly cookie is present but the in-memory token is lost.

Issue a fresh JWT for the current session › Responses

Fresh JWT token

token
​string · required

JWT token

GET/api/auth/token
curl --request GET \ --url https://api-chat.misindo.id/api/auth/token
shell
Example Responses
{ "token": "token" }
json
application/json

Register a new tenant organization

POST
https://api-chat.misindo.id
/api/auth/register

Self-service tenant registration. Creates a new organization and spawns provisioning in the background. Returns a JWT so the user can start using the app immediately while provisioning completes.

Register a new tenant organization › Request Body

org_name
​string · required

Name of the new organization

admin_email
​string · email · required

Email for the initial admin user

admin_password
​string · minLength: 6 · required

Password for the initial admin user (min 6 characters)

Register a new tenant organization › Responses

Organization created and provisioning started

token
​string

JWT token for immediate use

org_id
​string · uuid
message
​string
POST/api/auth/register
curl --request POST \ --url https://api-chat.misindo.id/api/auth/register \ --header 'Content-Type: application/json' \ --data ' { "org_name": "org_name", "admin_email": "test@example.com", "admin_password": "admin_password" } '
shell
Example Request Body
{ "org_name": "org_name", "admin_email": "test@example.com", "admin_password": "admin_password" }
json
Example Responses
{ "token": "token", "org_id": "00000000-0000-0000-0000-000000000000", "message": "message" }
json
application/json

Conversations