---
title: "Accept Pending Invite"
method: POST
path: "/api/voice/pending-invites/{invite_id}/accept"
tags: ["voice-control", "voice-control"]
---

# Accept Pending Invite

`POST /api/voice/pending-invites/{invite_id}/accept`

## Request

- Base URL: `https://api.dialogbrain.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.dialogbrain.com/api/voice/pending-invites/{invite_id}/accept`
- Auth: none declared

Operator clicked Join. Atomically claim the invite (first-click-wins
via UPDATE ... WHERE accepted_at IS NULL), then dispatch the bot via
POST /internal/telegram-voice/group-listen so it joins the call.

Race resolution: if the invite is already accepted/declined, return
409 — the inbox UI surfaces "Another teammate already accepted".

## Path parameters

- `invite_id` integer, required

## Request body

- RejoinRequest: Optional body for /rejoin and /coexist. `tab_id` is a per-tab UUID generated client-side (sessionStorage) and appended to the LK browser identity so multiple tabs/browsers logged in as the same user don't DUPLICATE_IDENTITY-kick each other in the LK room. Omit to fall back to the legacy `browser:{user}:{call}` shape (single-tab semantics — second tab WILL kick the first).
  - `tab_id` string, nullable

## Response `200`

Successful Response

- union
  - SrcApiVoiceControlAcceptInviteResponse: Response for 1:1 inbound pickup (telegram_1to1 + twilio_1to1). Single-shape (no error arm): failure modes raise HTTPException (502 / 409 / 410 etc.) so the body is never returned on error. The frontend's `acceptVoiceInvite` calls `apiClient.post`, which throws `APIError` on any non-2xx — try/catch handles failures uniformly with the outbound `/api/voice/user-call` flow. Per the unified-call-path plan (D3), `url`/`token`/`room` are REQUIRED so the frontend can mount `<CallContactOverlay>` directly without round-tripping through `/api/voice/rejoin/{call_id}`. This matches `StartUserCallResponse`'s shape, so both flows converge on the same overlay component with identical props.
    - `status` 'accepted', required
    - `invite_id` integer, required
    - `call_id` string, required
    - `url` string, required
    - `token` string, required
    - `room` string, required
  - AcceptGroupInviteResponse: Response for telegram_group invite pickup — operator brings the bot into the call but does NOT join as a publisher (the group listener Bot is the participant). No browser-side LK creds because the operator listens via the separate `<ListenOverlay>` flow, which mints its own subscriber token via `/api/voice/listen-in/{call_id}`. Kept distinct from `AcceptInviteResponse` (1:1 unified shape) so each path has a single, statically-checked contract — no Optional shims, no shared discriminator field. `voice_call_thread_channel_ref` is the channel_ref of the new `kind='voice_call'` sub-thread the bot's join creates — frontend uses this verbatim to navigate the inbox to the active-call view. Server-computed because Telegram's int64 tg_call_id loses precision when round-tripped through JS Number, so the frontend can't reliably reconstruct it from the lossy invite payload.
    - `status` 'accepted', required
    - `invite_id` integer, required
    - `call_id` string, nullable
    - `voice_call_thread_channel_ref` string, nullable
    - `surface` string, nullable

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/dialogbrain/apis/dialogbrain-v2-api-gateway.md) · [All operations](https://skmtc.dev/dialogbrain/apis/dialogbrain-v2-api-gateway/llms.txt) · [OpenAPI document](https://skmtc.dev/dialogbrain/apis/dialogbrain-v2-api-gateway/revisions/77bef09a9209?raw)
