Αναφορά API / Chat takeover

Chat takeover

Τα endpoints της ομάδας Chat takeover του Voiceland AI API, με παραμέτρους, σχήματα και παραδείγματα curl.

Τελευταία ενημέρωση:

Οι περιγραφές των endpoints και των πεδίων εμφανίζονται στα αγγλικά, όπως ακριβώς τις δημοσιεύει το API. Είναι επιλογή μας, ώστε να διαβάζετε εδώ ό,τι θα δείτε και στις αποκρίσεις.

GET /v1/takeover-presence#

List representative availability. Every representative's current availability row for this tenant. Availability decays: a row that has not been refreshed for a day stops counting, so a closed console cannot hold a queue open forever. The active load per representative is derived from the claimed sessions, never stored.

Αποκρίσεις

Κωδικός Περιγραφή
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Παράδειγμα αιτήματος

curl "https://api.voiceland.ai/v1/takeover-presence" \
  -H "Authorization: Bearer VL_API_KEY"

Η επιτυχής απόκριση επιστρέφει ένα TakeoverPresenceListResponse.

Παράδειγμα απόκρισης

{
  "items": [
    {
      "available": true,
      "capacity": 3,
      "display_name": "Maria",
      "rep_id": "maria@acme.example",
      "updated_at": "2026-08-06T09:00:00Z"
    }
  ]
}

PUT /v1/takeover-presence#

Set a representative's availability. Upserts one representative's availability flag and capacity (how many concurrent taken-over chats they will hold; declaring available without a capacity defaults it to 1). Re-send periodically to keep the row fresh, presence decays after a day without a refresh. Whether *anyone* is available is what decides the visitor's "no one is available right now" notice.

Σώμα αιτήματος

application/json Σχήμα: TakeoverPresencePutRequest

Πεδίο Τύπος Απαιτείται Περιγραφή
available boolean Ναι
capacity integer
display_name string
rep_id string Ναι

Αποκρίσεις

Κωδικός Περιγραφή
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Παράδειγμα αιτήματος

curl -X PUT "https://api.voiceland.ai/v1/takeover-presence" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "available": true,
  "capacity": 3,
  "display_name": "Maria",
  "rep_id": "maria@acme.example"
}'

Η επιτυχής απόκριση επιστρέφει ένα TakeoverPresenceView.

Παράδειγμα απόκρισης

{
  "available": true,
  "capacity": 3,
  "display_name": "Maria",
  "rep_id": "maria@acme.example"
}

GET /v1/takeovers#

List chat takeover sessions. One page of your chat sessions that ever asked for a human, in session-id order. ?state=pending_human is the waiting queue a representative picks from; ?state=human is the sessions currently held by one; ?state=ai is the history. **Paging.** Pass the next_cursor from the previous response back as ?cursor=. **An empty next_cursor is the only signal that you have seen everything**, the state filter is applied after each read, so a short page, including an empty one, with a cursor set is normal and means "ask again".

Παράμετροι

Όνομα Θέση Τύπος Απαιτείται Περιγραφή
state query string Filter: ai, pending_human or human. Applied after the read, short pages are normal.
limit query integer Rows per page, 1 to 100 (default 50). Larger values are capped rather than refused.
cursor query string The next_cursor from the previous page. Omit for the first page. A cursor belongs to the scope that issued it.

Αποκρίσεις

Κωδικός Περιγραφή
200 Success.
400 state is not one of the three states or limit is not a positive whole number (bad_request); or cursor was not issued by this listing (invalid_cursor), start again without it.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Παράδειγμα αιτήματος

curl "https://api.voiceland.ai/v1/takeovers" \
  -H "Authorization: Bearer VL_API_KEY"

Η επιτυχής απόκριση επιστρέφει ένα TakeoverListResponse.

Παράδειγμα απόκρισης

{
  "items": [
    {
      "agent": "front-desk",
      "reason": "visitor asked for a person",
      "requested_at": "2026-08-06T09:15:04Z",
      "session_id": "widget-8c2f1a7e-4b3d-4e21-9c0a-5f6d7e8a9b0c",
      "state": "pending_human",
      "trigger": "visitor"
    }
  ],
  "next_cursor": ""
}

GET /v1/takeovers/{session_id}#

Get one takeover session. One session's takeover record. While the session is waiting (pending_human), queue_position carries its 1-based place in the tenant's waiting line.

Παράμετροι

Όνομα Θέση Τύπος Απαιτείται Περιγραφή
session_id path string Ναι The chat session id (the same id the call log uses).

Αποκρίσεις

Κωδικός Περιγραφή
200 Success.
401 Missing or invalid API key.
404 That session never requested a takeover (takeover_not_found).
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Παράδειγμα αιτήματος

curl "https://api.voiceland.ai/v1/takeovers/{session_id}" \
  -H "Authorization: Bearer VL_API_KEY"

Η επιτυχής απόκριση επιστρέφει ένα TakeoverSessionView.

Παράδειγμα απόκρισης

{
  "agent": "front-desk",
  "queue_position": 2,
  "reason": "could not answer after repeated attempts",
  "requested_at": "2026-08-06T09:15:04Z",
  "session_id": "widget-8c2f1a7e-4b3d-4e21-9c0a-5f6d7e8a9b0c",
  "state": "pending_human",
  "trigger": "llm"
}

POST /v1/takeovers/{session_id}/claim#

Claim a waiting session. Atomically assigns a waiting session to one representative and moves it to human. **Exactly one claim wins**: when two representatives race for the same session, the loser gets 409 and should pick another from the queue. From this moment the assistant stays silent and replies go through POST /takeovers/{session_id}/reply. **The response carries claim_token, and it is shown only once.** It is the proof of this claim, and EVERY route that touches the session afterwards requires it in the X-Takeover-Claim header: the two reads (/feed, /history), the draft (/assist) and the three writes (/reply, /resume, /close). claimed_by is a value the queue listing displays to everyone, so holding the claim, not knowing the claimant's name, is what authorizes reading a visitor's words, speaking to them, or ending the episode. Store it for the life of the episode; it cannot be re-read or re-issued, and it stops working the moment the episode ends. **take_over: true claims a session that is ALREADY HELD**, displacing its holder: their claim_token stops working and claimed_by becomes the caller, in one conditional write. It is the recovery path for a lost token, without it, a session whose token is gone could never be answered or ended and the visitor would be left in a chat nobody can close. It grants nothing a caller could not already reach with resume + request + claim; what it changes is that the displacement is a single audited action under the CALLER'S OWN rep_id instead of a sequence whose first step wore the previous holder's name. It answers 409 on a session nobody holds, claim those with the ordinary form, which still loses a race rather than displacing the winner.

Παράμετροι

Όνομα Θέση Τύπος Απαιτείται Περιγραφή
session_id path string Ναι The waiting session id (or, with take_over, a session already held).

Σώμα αιτήματος

application/json Σχήμα: TakeoverClaimRequest

Πεδίο Τύπος Απαιτείται Περιγραφή
rep_id string Ναι
rep_name string
take_over boolean

Αποκρίσεις

Κωδικός Περιγραφή
200 Success.
401 Missing or invalid API key.
404 That session never requested a takeover (takeover_not_found).
409 The session is not waiting, another representative already claimed it, or the visitor cancelled. With take_over: true, the session is not currently held by anybody (takeover_conflict).
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Παράδειγμα αιτήματος

curl -X POST "https://api.voiceland.ai/v1/takeovers/{session_id}/claim" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "rep_id": "maria@acme.example",
  "rep_name": "Maria"
}'

Η επιτυχής απόκριση επιστρέφει ένα TakeoverClaimResponse.

Παράδειγμα απόκρισης

{
  "agent": "front-desk",
  "claim_token": "9f2c…",
  "claimed_at": "2026-08-06T09:15:41Z",
  "claimed_by": "maria@acme.example",
  "session_id": "widget-8c2f…",
  "state": "human"
}

POST /v1/takeovers/{session_id}/close#

Close the takeover as handled. Ends the human segment with resolution closed: the representative considers the conversation handled. The chat session itself may live on with the assistant, ending the chat is the visitor's move. **Requires the X-Takeover-Claim header**, for the same reason /resume does.

Παράμετροι

Όνομα Θέση Τύπος Απαιτείται Περιγραφή
session_id path string Ναι The claimed session id.
X-Takeover-Claim header string Ναι The claim_token from this session's claim. Proof that you hold the claim; it is not a substitute for your API key.

Σώμα αιτήματος

application/json Σχήμα: TakeoverRepRequest

Πεδίο Τύπος Απαιτείται Περιγραφή
rep_id string Ναι
rep_name string

Αποκρίσεις

Κωδικός Περιγραφή
200 Success.
400 rep_id or the X-Takeover-Claim header is missing (bad_request).
401 Missing or invalid API key.
404 That session never requested a takeover (takeover_not_found).
409 This session is not held by the caller: another representative holds it, the claim token does not match, or the episode already ended (takeover_conflict).
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Παράδειγμα αιτήματος

curl -X POST "https://api.voiceland.ai/v1/takeovers/{session_id}/close" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "rep_id": "maria@acme.example"
}'

Η επιτυχής απόκριση επιστρέφει ένα TakeoverSessionView.

Παράδειγμα απόκρισης

{
  "resolution": "closed",
  "resolved_at": "2026-08-06T09:24:10Z",
  "session_id": "widget-8c2f…",
  "state": "ai"
}

GET /v1/takeovers/{session_id}/feed#

Join the live feed of a claimed session. Mints a short-lived, subscribe-only join grant for the session's realtime conversation stream, so the claiming representative sees the visitor's messages as they are typed. topics names the streams to subscribe to: visitor_turns (what the visitor types), agent_turns (assistant and human bubbles), transcript (role-tagged turn frames) and takeover (state changes). The grant is read-only by design, replies go through POST /takeovers/{session_id}/reply so every human turn is validated, attributed and recorded on the transcript. **Requires the X-Takeover-Claim header**: the claim_token returned by POST /takeovers/{session_id}/claim. The feed carries the visitor's live words, and claimed_by is visible to everyone who can list the queue, so holding the claim, not knowing the claimant's name, is what opens it.

Παράμετροι

Όνομα Θέση Τύπος Απαιτείται Περιγραφή
session_id path string Ναι The claimed session id.
rep_id query string Ναι The claiming representative's id, the feed is only issued to the claimant.
X-Takeover-Claim header string Ναι The claim_token from this session's claim. Proof that you hold the claim; it is not a substitute for your API key.

Αποκρίσεις

Κωδικός Περιγραφή
200 Success.
401 Missing or invalid API key.
404 That session never requested a takeover (takeover_not_found).
409 You do not hold this session: it is not claimed, it is claimed by someone else, or the X-Takeover-Claim token does not match (takeover_conflict). The three are deliberately indistinguishable, a refusal that told them apart would confirm whether a guessed rep_id is the real claimant.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Παράδειγμα αιτήματος

curl "https://api.voiceland.ai/v1/takeovers/{session_id}/feed" \
  -H "Authorization: Bearer VL_API_KEY"

Η επιτυχής απόκριση επιστρέφει ένα TakeoverFeedResponse.

Παράδειγμα απόκρισης

{
  "expires_in_s": 900,
  "livekit_url": "wss://rt.example.com",
  "room": "widget-8c2f…",
  "token": "eyJhb…",
  "topics": {
    "agent_turns": "lk.transcription",
    "takeover": "vl.takeover",
    "transcript": "transcript",
    "visitor_turns": "lk.chat"
  }
}

GET /v1/takeovers/{session_id}/history#

Read what was said before you claimed. The conversation as it stood while the visitor was waiting, so the representative who claims a chat does not start reading it mid-sentence. The live feed can only show what arrives after you join it, and the full transcript is only written when the session ends; this is the part in between. It is a **bounded snapshot**, not a log: the newest turns are kept, and truncated: true means older ones were dropped. as_of is when the snapshot was taken; compare it with the session's claimed_at to see how much of the wait it covers. offset_ms is the same anchor the live feed's transcript frames carry, so turns that appear in both can be matched. Answers 200 with an empty turns list when nothing was captured - a chat claimed the instant it opened has no history to show. **Requires the X-Takeover-Claim header**, exactly like the live feed and for the same reason: this is the visitor's own words, and it answers only the holder of the claim.

Παράμετροι

Όνομα Θέση Τύπος Απαιτείται Περιγραφή
session_id path string Ναι The claimed session id.
rep_id query string Ναι The claiming representative's id. The history carries the visitor's words, so it is only issued to the claimant.
X-Takeover-Claim header string Ναι The claim_token from this session's claim. Proof that you hold the claim; it is not a substitute for your API key.

Αποκρίσεις

Κωδικός Περιγραφή
200 Success.
401 Missing or invalid API key.
404 That session never requested a takeover (takeover_not_found).
409 You do not hold this session: it is not claimed, it is claimed by someone else, or the X-Takeover-Claim token does not match (takeover_conflict). The three are deliberately indistinguishable, a refusal that told them apart would confirm whether a guessed rep_id is the real claimant.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Παράδειγμα αιτήματος

curl "https://api.voiceland.ai/v1/takeovers/{session_id}/history" \
  -H "Authorization: Bearer VL_API_KEY"

Η επιτυχής απόκριση επιστρέφει ένα TakeoverHistoryResponse.

Παράδειγμα απόκρισης

{
  "as_of": "2026-08-06T09:14:33Z",
  "session_id": "widget-8c2f…",
  "turns": [
    {
      "at": "2026-08-06T09:14:02Z",
      "offset_ms": 4120,
      "role": "caller",
      "text": "My invoice for March looks wrong."
    },
    {
      "at": "2026-08-06T09:14:05Z",
      "offset_ms": 7480,
      "role": "agent",
      "text": "I can look at that with you. Which amount were you expecting?"
    },
    {
      "at": "2026-08-06T09:14:31Z",
      "offset_ms": 33200,
      "role": "caller",
      "text": "Can I speak to a person please?"
    }
  ]
}

POST /v1/takeovers/{session_id}/reply#

Send a human reply into a claimed session. Delivers one reply from the claiming representative to the visitor. It renders in the widget as a human bubble, distinct from the assistant's, and lands on the transcript under the human_agent role, so every turn of a taken-over session stays attributable. **Requires the X-Takeover-Claim header**: the claim_token returned by POST /takeovers/{session_id}/claim. This is the call that puts WORDS IN FRONT OF A CUSTOMER attributed to rep_id, and rep_id is a value the caller writes while claimed_by is visible to everyone who can list the queue, so possession of the claim, not knowledge of the claimant's name, is what authorizes it. Missing header is 400; a wrong token, another representative's session, or an episode that already ended is 409. Set suggested_by_ai when the text came from an assist draft (POST /takeovers/{session_id}/assist or POST /assist/suggest), whether you sent it as-is or edited it first. The transcript turn records it, which is what keeps the answer-quality numbers honest about what a machine wrote and what a person did.

Παράμετροι

Όνομα Θέση Τύπος Απαιτείται Περιγραφή
session_id path string Ναι The claimed session id.
X-Takeover-Claim header string Ναι The claim_token from this session's claim. Proof that you hold the claim; it is not a substitute for your API key.

Σώμα αιτήματος

application/json Σχήμα: TakeoverReplyRequest

Πεδίο Τύπος Απαιτείται Περιγραφή
rep_id string Ναι
rep_name string
suggested_by_ai boolean
text string Ναι

Αποκρίσεις

Κωδικός Περιγραφή
200 Success.
400 rep_id or the X-Takeover-Claim header is missing (bad_request).
401 Missing or invalid API key.
404 That session never requested a takeover (takeover_not_found).
409 This session is not held by the caller: another representative holds it, the claim token does not match, or the episode already ended. One answer for all of them, so a refusal cannot be used to test a guess (takeover_conflict).
410 The chat session ended, the reply was NOT delivered (session_gone).
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Παράδειγμα αιτήματος

curl -X POST "https://api.voiceland.ai/v1/takeovers/{session_id}/reply" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "rep_id": "maria@acme.example",
  "rep_name": "Maria",
  "suggested_by_ai": false,
  "text": "Hi, Maria here, happy to help with your order."
}'

Παράδειγμα απόκρισης

{
  "sent": true,
  "suggested_by_ai": false
}

POST /v1/takeovers/{session_id}/request#

Force a takeover on a live chat session. Moves a live chat session into the waiting queue on the operator's initiative, the third trigger next to the assistant's own judgement and the visitor's button. The assistant stops answering immediately; the visitor sees the transfer notice and their queue position. Idempotent while an episode is live: requesting a session that is already waiting or already with a human answers 200 with its current standing, untouched.

Παράμετροι

Όνομα Θέση Τύπος Απαιτείται Περιγραφή
session_id path string Ναι The live chat session id.

Σώμα αιτήματος

application/json Σχήμα: TakeoverConsoleRequest

Πεδίο Τύπος Απαιτείται Περιγραφή
agent string Ναι
reason string
rep_id string

Αποκρίσεις

Κωδικός Περιγραφή
200 Success.
401 Missing or invalid API key.
403 Human takeover is switched off for that assistant (takeover_disabled). Turn on web_widget.enabled and web_widget.takeover.enabled first: without them the visitor's widget cannot show the transfer or let them cancel it, so forcing one would leave them in a chat the assistant has stopped answering and they cannot get out of.
404 No agent with that name in this project (agent_not_found).
410 The chat session has already ended, there is nobody to hand over (session_gone).
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Παράδειγμα αιτήματος

curl -X POST "https://api.voiceland.ai/v1/takeovers/{session_id}/request" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "agent": "front-desk",
  "reason": "visitor sounds frustrated"
}'

Η επιτυχής απόκριση επιστρέφει ένα TakeoverRequestResponse.

Παράδειγμα απόκρισης

{
  "queue_position": 1,
  "rep_available": true,
  "session": {
    "agent": "front-desk",
    "session_id": "widget-8c2f…",
    "state": "pending_human",
    "trigger": "console"
  },
  "waiting_count": 1
}

POST /v1/takeovers/{session_id}/resume#

Hand the chat back to the assistant. Ends the human segment with resolution resumed: the assistant answers the next visitor message again, with the human's replies in its context. **Requires the X-Takeover-Claim header**, exactly as /reply does. Ending an episode is not a lesser act than writing into one, the representative holding the chat is cut off and the visitor's conversation goes back to the assistant, and it used to cost only the claimed_by printed in the queue listing. If you no longer hold the token for a session you need to end, claim it with take_over: true first; that puts your own rep_id on the row before you touch it.

Παράμετροι

Όνομα Θέση Τύπος Απαιτείται Περιγραφή
session_id path string Ναι The claimed session id.
X-Takeover-Claim header string Ναι The claim_token from this session's claim. Proof that you hold the claim; it is not a substitute for your API key.

Σώμα αιτήματος

application/json Σχήμα: TakeoverRepRequest

Πεδίο Τύπος Απαιτείται Περιγραφή
rep_id string Ναι
rep_name string

Αποκρίσεις

Κωδικός Περιγραφή
200 Success.
400 rep_id or the X-Takeover-Claim header is missing (bad_request).
401 Missing or invalid API key.
404 That session never requested a takeover (takeover_not_found).
409 This session is not held by the caller: another representative holds it, the claim token does not match, or the episode already ended (takeover_conflict).
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Παράδειγμα αιτήματος

curl -X POST "https://api.voiceland.ai/v1/takeovers/{session_id}/resume" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "rep_id": "maria@acme.example"
}'

Η επιτυχής απόκριση επιστρέφει ένα TakeoverSessionView.

Παράδειγμα απόκρισης

{
  "resolution": "resumed",
  "resolved_at": "2026-08-06T09:24:10Z",
  "session_id": "widget-8c2f…",
  "state": "ai"
}

Σχήματα#

Error#

Error envelope returned for non-2xx responses.

Πεδίο Τύπος Απαιτείται Περιγραφή
error object Ναι

TakeoverClaimRequest#

Πεδίο Τύπος Απαιτείται Περιγραφή
rep_id string Ναι
rep_name string
take_over boolean

TakeoverClaimResponse#

Πεδίο Τύπος Απαιτείται Περιγραφή
agent string Ναι
claim_token string Ναι
claimed_at string (date-time)
claimed_by string
queue_position integer
reason string
requested_at string (date-time)
resolution string
resolved_at string (date-time)
session_id string Ναι
state string Ναι
trigger string

TakeoverConsoleRequest#

Πεδίο Τύπος Απαιτείται Περιγραφή
agent string Ναι
reason string
rep_id string

TakeoverFeedResponse#

Πεδίο Τύπος Απαιτείται Περιγραφή
expires_in_s integer Ναι
livekit_url string Ναι
room string Ναι
token string Ναι
topics map of string Ναι

TakeoverHistoryResponse#

Πεδίο Τύπος Απαιτείται Περιγραφή
as_of string (date-time)
session_id string Ναι
truncated boolean
turns array of TakeoverHistoryTurnView Ναι

TakeoverHistoryTurnView#

Πεδίο Τύπος Απαιτείται Περιγραφή
at string (date-time)
offset_ms integer
role string Ναι
text string Ναι

TakeoverListResponse#

Πεδίο Τύπος Απαιτείται Περιγραφή
items array of TakeoverSessionView Ναι
next_cursor string Ναι

TakeoverPresenceListResponse#

Πεδίο Τύπος Απαιτείται Περιγραφή
items array of TakeoverPresenceView Ναι

TakeoverPresencePutRequest#

Πεδίο Τύπος Απαιτείται Περιγραφή
available boolean Ναι
capacity integer
display_name string
rep_id string Ναι

TakeoverPresenceView#

Πεδίο Τύπος Απαιτείται Περιγραφή
available boolean Ναι
capacity integer Ναι
display_name string
rep_id string Ναι
updated_at string (date-time)

TakeoverRepRequest#

Πεδίο Τύπος Απαιτείται Περιγραφή
rep_id string Ναι
rep_name string

TakeoverReplyRequest#

Πεδίο Τύπος Απαιτείται Περιγραφή
rep_id string Ναι
rep_name string
suggested_by_ai boolean
text string Ναι

TakeoverRequestResponse#

Πεδίο Τύπος Απαιτείται Περιγραφή
out_of_hours boolean
queue_position integer
rep_available boolean Ναι
session TakeoverSessionView Ναι
waiting_count integer

TakeoverSessionView#

Πεδίο Τύπος Απαιτείται Περιγραφή
agent string Ναι
claimed_at string (date-time)
claimed_by string
queue_position integer
reason string
requested_at string (date-time)
resolution string
resolved_at string (date-time)
session_id string Ναι
state string Ναι
trigger string

Η κονσόλα

Οι σελίδες αυτές είναι μόνο για ανάγνωση. Η δοκιμαστική κλήση, τα κλειδιά API και η ζωντανή αναφορά API βρίσκονται στην κονσόλα, όπου ο λογαριασμός σας είναι συνδεδεμένος.

Άνοιγμα κονσόλας