# Mark a callback done

`POST https://api.morevoice.ai/v1/callbacks/{id}/complete`

Closes an open callback that was resolved another way (409 while it is on a call). Emits `callback.completed`. Needs a live key.

Authenticate with a secret API key: `Authorization: Bearer $MOREVOICE_API_KEY`.

Operation ID: `callbacks_complete`.

## Parameters

### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `string` | yes | A callback ID (`cb_…`). |

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `MoreVoice-Version` | `string` | no | The API version to use for this request. Defaults to the version the API key is pinned to. |
| `Idempotency-Key` | `string` | no | A unique key (for example a UUID) that makes this request safe to retry: for 24 hours, a retry with the same key and parameters returns the first response instead of acting twice. |

## Request body

Optional, `application/json`.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `note` | `string` | no | How it was resolved (added to the notes). |

Example:

```json
{
  "note": "Reached by email"
}
```

## Responses

### 200 OK

OK Returns `Callback`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | `"callback"` | — |
| `id` | `string` | A callback ID (prefix `cb_`). |
| `livemode` | `boolean` | `true` in live mode, `false` in test mode. |
| `phone` | `string` | The number to call back, E.164. |
| `name` | `string` | The person's name, when known. |
| `status` | `string` | `pending` (waiting for its time), `offered` (ringing an agent), `dialing`, `connected` (on the call back), `completed`, `failed` (attempts used up), `cancelled` or `expired` (past its window, or too old). |
| `source` | `string` | Where the request came from: `queue` (a caller pressed the callback key), `ivr`, `flow`, `ai` (the assistant booked it), `web` (a website form), `manual`, `campaign`, `voicemail` or `api`. |
| `site_id` | `string \| null` | The website form it came from (`source` = web). |
| `due_at` | `string` | The earliest time to call back (moved into business hours). |
| `window_end` | `string \| null` | Don't call after this time; null: no limit. |
| `priority` | `integer` | 1 (low) … 10 (urgent); higher is returned sooner. |
| `route` | `string` | Who returns it: `agent_queue` (offered to the next free agent of `queue_id`, then dialled), `agent` (`agent_id` calls back) or `assistant` (the AI `assistant_id` calls back). |
| `queue_id` | `string \| null` | `q_…` ID. |
| `agent_id` | `string \| null` | `usr_…` ID. |
| `assistant_id` | `string \| null` | `asst_…` ID. |
| `attempts` | `integer` | Call-back attempts made so far. |
| `max_attempts` | `integer` | — |
| `last_attempt_at` | `string \| null` | — |
| `last_result` | `string \| null` | The last attempt's result, e.g. `answered`, `no-answer`, `busy`, `done-manually`. |
| `call_id` | `string \| null` | `call_…` ID. |
| `origin_call_id` | `string \| null` | `call_…` ID. |
| `notes` | `string` | Notes for whoever returns it (each note is stamped with its time and author). |
| `summary` | `string \| null` | The AI summary of the originating call, when there is one. |
| `sla_at` | `string \| null` | When it should have been returned by (the SLA target, in business hours). |
| `merged_requests` | `integer` | Later requests for the same number merged into this one. |
| `context` | `object` | — |
| `context.web` | `object \| null` | Web-form requests: the page and language of the form. |
| `metadata` | `Metadata` | Up to 50 key/value pairs (keys up to 40 characters, values up to 500) you attach to an object. Returned as sent. |
| `completed_at` | `string \| null` | — |
| `created` | `string` | An ISO-8601 timestamp in UTC. |
| `updated` | `string` | An ISO-8601 timestamp in UTC. |

Example:

```json
{
  "agent_id": null,
  "assistant_id": null,
  "attempts": 0,
  "call_id": null,
  "completed_at": null,
  "context": {
    "web": null
  },
  "created": "2026-11-03T09:14:22.000Z",
  "due_at": "2026-11-03T10:00:00.000Z",
  "id": "cb_2dXk9QmZ4rTv",
  "last_attempt_at": null,
  "last_result": null,
  "livemode": true,
  "max_attempts": 3,
  "merged_requests": 0,
  "metadata": {
    "crm_ticket": "T-1042"
  },
  "name": "Dana Levi",
  "notes": "Asked about the renewal offer.",
  "object": "callback",
  "origin_call_id": null,
  "phone": "+972501234567",
  "priority": 5,
  "queue_id": "q_3hRf8Kd2LmPq",
  "route": "agent_queue",
  "site_id": null,
  "sla_at": "2026-11-03T11:00:00.000Z",
  "source": "api",
  "status": "pending",
  "summary": null,
  "updated": "2026-11-03T09:14:22.000Z",
  "window_end": null
}
```

### 400 Bad Request

The request is invalid: a parameter is missing, malformed or unknown, or the version header is unknown. Returns `ErrorEnvelope`.

### 401 Unauthorized

No valid API key was sent. Returns `ErrorEnvelope`.

### 403 Forbidden

The key may not do this (a missing scope, a plan limit, or a compliance block). Returns `ErrorEnvelope`.

### 404 Not Found

No object with this ID exists in this organisation and mode. Returns `ErrorEnvelope`.

### 409 Conflict

The request conflicts with the object's state, or the Idempotency-Key was reused with other parameters. Returns `ErrorEnvelope`.

### 429 Too Many Requests

Too many requests, or no call capacity right now. Retry after the Retry-After delay. Returns `ErrorEnvelope`.

### 500 Internal Server Error

Something went wrong on MoreVoice's side. Retry with the same Idempotency-Key. Returns `ErrorEnvelope`.

## Code samples

**TypeScript**

```ts
import MoreVoice from "@morevoice/sdk";

const mv = new MoreVoice(); // MOREVOICE_API_KEY from the environment

const callback = await mv.callbacks.complete("cb_7Hk2Lm9Qp", {
	note: "Reached by email",
});
console.log(callback);
```

**Python**

```python
from morevoice import MoreVoice

client = MoreVoice()  # MOREVOICE_API_KEY from the environment

callback = client.callbacks.complete("cb_7Hk2Lm9Qp", {
    "note": "Reached by email",
})
print(callback)
```

**cURL**

```sh
curl -X POST https://api.morevoice.ai/v1/callbacks/cb_7Hk2Lm9Qp/complete \
  -H "Authorization: Bearer $MOREVOICE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "note": "Reached by email"
}'
```
