Skip to content

REST API

Calls (LiveKit)

Audio/video calls over LiveKit: start, join, heartbeat, end, diagnostics.

Calls run on a LiveKit media server; the API hands out room tokens and keeps the call state. Flow: caller call/start → callees get CallStarted (+ FCM type=call) → callee call/token (caller gets CallAnswered) → both connect to LiveKit with url + token and send call/ping → call/end (everyone gets CallEnded). Calls are not available in channels.

Endpoints#

GET /api/calls/config #

Call configuration

Bearer token

LiveKit availability, server URL, ring and token TTL.

Parameters

No parameters.

Request

curl
curl 'https://minchatapp.com/api/calls/config' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Accept: application/json'

Response

HTTP 200
{
  "enabled": false,
  "url": "",
  "ring_ttl": 45,
  "token_ttl": 3600
}
POST /api/conversations/{conversation}/call/start #

Start a call

Bearer token Rate limit: 30/min

Private chats and groups (channels → 400). Returns a LiveKit token, url, room, call_id. If a call is already active you rejoin (rejoined:true). If the callee is unreachable the call ends at once (callee_reachable:false, reason:"unavailable"). Callees get CallStarted and an FCM push type=call.

Parameters

Name Type Description
conversation
required path
integer
Conversation id.
mode
optional body
string
audio (default) or video.
one of: audio, video

Request

curl
curl -X POST 'https://minchatapp.com/api/conversations/12/call/start' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"mode": "video"}'

Response

HTTP 503
{
  "success": false,
  "code": "call.unavailable",
  "error": "Calls are temporarily unavailable",
  "message": "Calls are temporarily unavailable"
}
GET /api/conversations/{conversation}/call/token #

Join the active call

Bearer token

Token for the active call (answering). 404 call.none_active if there is none. Caller gets CallAnswered.

Parameters

Name Type Description
conversation
required path
integer
Conversation id.

Request

curl
curl 'https://minchatapp.com/api/conversations/12/call/token' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Accept: application/json'

Response

HTTP 503
{
  "success": false,
  "code": "call.unavailable",
  "error": "Calls are temporarily unavailable",
  "message": "Calls are temporarily unavailable"
}
GET /api/conversations/{conversation}/call/token/refresh #

Refresh the call token

Bearer token

New JWT without side effects (no “answered” mark).

Parameters

Name Type Description
conversation
required path
integer
Conversation id.

Request

curl
curl 'https://minchatapp.com/api/conversations/12/call/token/refresh' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Accept: application/json'

Response

Responds with HTTP 200.

POST /api/conversations/{conversation}/call/ping #

Call heartbeat

Bearer token Rate limit: 240/min

Send every few seconds while in the call; active:false means it has ended.

Parameters

Name Type Description
conversation
required path
integer
Conversation id.
call_id
required body
string
Call id from call/start / CallStarted.

Request

curl
curl -X POST 'https://minchatapp.com/api/conversations/12/call/ping' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"call_id": "<uuid>"}'

Response

Responds with HTTP 200.

POST /api/conversations/{conversation}/call/stats #

Report call quality

Bearer token Rate limit: 60/min

Logged server-side.

Parameters

Name Type Description
conversation
required path
integer
Conversation id.
call_id
optional body
string
Call id from call/start / CallStarted.
duration
optional body
integer
Duration in seconds.
≥ 0
reconnects
optional body
integer
Number of reconnects.
≥ 0
ice
optional body
string
Selected ICE candidate type.
max 32 chars
loss
optional body
number
Packet loss, %.
rtt
optional body
number
Round-trip time, ms.
jitter
optional body
number
Jitter, ms.

Request

curl
curl -X POST 'https://minchatapp.com/api/conversations/12/call/stats' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"call_id": "<uuid>", "duration": 120, "rtt": 45.2}'

Response

Responds with HTTP 200.

POST /api/conversations/{conversation}/call/end #

End / decline a call

Bearer token Rate limit: 60/min

Only the exact call_id is ended. Everyone gets CallEnded.

Parameters

Name Type Description
conversation
required path
integer
Conversation id.
call_id
optional body
string
Call id from call/start / CallStarted.
reason
optional body
string
End reason.
one of: ended, cancelled, declined, timeout, busy
duration
optional body
integer
Duration in seconds.
≥ 0

Request

curl
curl -X POST 'https://minchatapp.com/api/conversations/12/call/end' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"call_id": "<uuid>", "reason": "ended", "duration": 120}'

Response

Responds with HTTP 200.

POST /api/calls/connect-report #

Report connection diagnostics

Bearer token Rate limit: 30/min

ICE/relay diagnostics from clients.

Parameters

Name Type Description
call_id
optional body
string
Call id from call/start / CallStarted.
max 64 chars
conversation_id
optional body
integer
Conversation id.
≥ 1
outcome
required body
string
Connection outcome.
one of: connected, failed, ice_failed, timeout, disconnected
phase
optional body
string
Connection phase.
one of: connect, reconnect, in_call
platform
optional body
string
Client platform.
max 32 chars
client_version
optional body
string
App version.
max 64 chars
attempts
optional body
integer
Connection attempts.
≥ 0≤ 50
elapsed_ms
optional body
integer
Time to connect, ms.
≥ 0≤ 3600000
candidates_tried
optional body
array
ICE candidate types tried.
max 10 items
candidates_tried.*
optional body
string
Candidate type.
one of: host, srflx, prflx, relay
relay_protocols
optional body
array
TURN protocols tried.
max 5 items
relay_protocols.*
optional body
string
Protocol.
one of: udp, tcp, tls
selected_local
optional body
string
Selected local candidate type.
one of: host, srflx, prflx, relay
selected_remote
optional body
string
Selected remote candidate type.
one of: host, srflx, prflx, relay
selected_relay_protocol
optional body
string
Selected relay protocol.
one of: udp, tcp, tls
network_type
optional body
string
Network type (wifi, cellular…).
max 32 chars
disconnect_reason
optional body
string
Disconnect reason.
max 64 chars
error
optional body
string
Error text.
max 500 chars

Request

curl
curl -X POST 'https://minchatapp.com/api/calls/connect-report' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"outcome": "connected", "phase": "connect", "platform": "web", "attempts": 1, "elapsed_ms": 840, "candidates_tried": ["host", "srflx"]}'

Response

HTTP 200
{
  "ok": true
}
POST /api/webhooks/livekit #

LiveKit webhook (internal)

LiveKit signature Rate limit: 120/min

Server-to-server endpoint for the LiveKit media server (room_finished clears stuck calls). Authenticated by LiveKit's JWT signature; not for third-party use.

Parameters

No parameters.

Request

curl
curl -X POST 'https://minchatapp.com/api/webhooks/livekit' \
  -H 'Accept: application/json'

Response

Responds with HTTP 200.