> ## Documentation Index
> Fetch the complete documentation index at: https://docs.corafone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# call.completed

> Webhook event sent when a call's status is updated to Completed.

## Event

`call.completed`

Sent when an existing call's `status` is **updated** to `Completed` (for example, from `Processing` or `Queued`). This follows the call change stream on status updates; a call **inserted** already as `Completed` does not trigger this webhook from that path. Delivered inside the [standard webhook envelope](/webhooks); the fields below are the inner `payload` object. Emission is gated by server configuration; if the outbound emitter is disabled, no webhook is sent.

## Payload fields

These fields are on the inner `payload` object (inside the [standard envelope](/webhooks)).

| Field          | Required | Description                                                                                                                                                                                                                                                                                                                                                                         |
| -------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `callId`       | **Yes**  | Internal call id.                                                                                                                                                                                                                                                                                                                                                                   |
| `phoneNumber`  | **No**   | Dialed or caller number in E.164 (e.g. `+15125550123`). **Omitted entirely** when a full, valid E.164 number isn't available — for example a non-telephonic call, or when only a partial/invalid value (such as a bare country code like `+1`) was captured. The field is never sent as a partial or invalid value, so treat it as optional and absent when no valid number exists. |
| `fileNumber`   | **No**   | The filenumber on the Account, either provided by submission or generated if no external id provided.                                                                                                                                                                                                                                                                               |
| `status`       | **Yes**  | Call status; for this event, always `Completed` (same casing as stored on the call record).                                                                                                                                                                                                                                                                                         |
| `duration`     | **Yes**  | Call length in **milliseconds** (`durationMs` on the call); `0` if not set.                                                                                                                                                                                                                                                                                                         |
| `direction`    | **No**   | Call direction from the agent config that handled the call: `INBOUND` for incoming agents, `OUTBOUND` for outgoing agents. 'UNKNOWN' when the direction cannot be resolved; treat an absent value as unknown.                                                                                                                                                                       |
| `isTestCall`   | **Yes**  | `true` when the call is classified as a test call; otherwise `false`. See [Test call classification](#test-call-classification).                                                                                                                                                                                                                                                    |
| `outcomes`     | **Yes**  | Object of outcome flags (see below). Always present; may be `{}` if nothing was detected.                                                                                                                                                                                                                                                                                           |
| `summary`      | **Yes**  | Call note or summary. May be an empty string.                                                                                                                                                                                                                                                                                                                                       |
| `recordingUrl` | **No**   | URL to the call recording on Cora's API. **Authenticated endpoint** — requires `X-User-Email` + `X-API-Key` headers; see [Fetching `recordingUrl`](#fetching-recordingurl). Omitted if no recording is available.                                                                                                                                                                   |
| `createdAt`    | **Yes**  | Timestamp from the call record. ISO-8601                                                                                                                                                                                                                                                                                                                                            |
| `endedAt`      | **Yes**  | Timestamp when the webhook payload was built. ISO-8601                                                                                                                                                                                                                                                                                                                              |

### Direction

`direction` is included when Cora can resolve the agent config for the completed call. Cora uses the main agent to determine the value. If the agent config cannot be resolved, `direction` is omitted instead of sending an `UNKNOWN` string; consumers should treat a missing `direction` as unknown.

### Test call classification

`isTestCall` is `true` when any of these conditions apply:

* The call was made through a test-call flow, including edit-agent phone and browser test calls.
* The call was manually triggered from an account page.
* The call was made to or received from an agent in test mode.
* The call was made to or received from a phone number listed as a test phone number on an account.

### Outcomes

Every property in `outcomes` is **optional**: only keys with values from call analysis (or label fallbacks) are included. Before delivery, the webhook removes any outcome keys that are not approved for external consumers; those keys never appear in the payload. The tables below list **possible** keys that may be sent after that filtering, grouped for readability.

#### Collection

| Field                  | Required | Type    | Definition                                                                                       |
| ---------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------ |
| `refuseToPay`          | **No**   | boolean | Refused to pay.                                                                                  |
| `dispute`              | **No**   | boolean | Debt disputed on the call.                                                                       |
| `engaged_negotiations` | **No**   | boolean | Consumer engaged in payment negotiation (e.g. adjusted amounts or explored options).             |
| `acknowledgeDebt`      | **No**   | boolean | Consumer acknowledged the debt.                                                                  |
| `payDate`              | **No**   | boolean | Pay frequency or pay date was discussed.                                                         |
| `sentSms`              | **No**   | boolean | Follow-up SMS was sent.                                                                          |
| `useLenderAgain`       | **No**   | boolean | Whether the consumer would use the lender again (`true` / `false`); omitted when not determined. |

#### Language

| Field         | Required | Type    | Definition               |
| ------------- | -------- | ------- | ------------------------ |
| `spanishCall` | **No**   | boolean | Call handled in Spanish. |

#### Contact

| Field               | Required | Type    | Definition                                                       |
| ------------------- | -------- | ------- | ---------------------------------------------------------------- |
| `confirmedName`     | **No**   | boolean | Name was confirmed.                                              |
| `deceased`          | **No**   | boolean | Subject indicated as deceased.                                   |
| `wantedToTalkHuman` | **No**   | boolean | Asked for a human agent.                                         |
| `statusTransfer`    | **No**   | boolean | Call transferred due to status (e.g. to another queue or agent). |
| `wasTheRightNumber` | **No**   | boolean | Reached the intended number.                                     |
| `wasTheRightParty`  | **No**   | boolean | Reached the correct party or debtor.                             |
| `wasWrongNumber`    | **No**   | boolean | Wrong number.                                                    |
| `wasWrongParty`     | **No**   | boolean | Wrong person.                                                    |

#### Compliance

| Field                     | Required | Type    | Definition                            |
| ------------------------- | -------- | ------- | ------------------------------------- |
| `ceaseAndDesist`          | **No**   | boolean | Cease-communication request.          |
| `complaintAboutCollector` | **No**   | boolean | Complaint about the collector.        |
| `doNotCall`               | **No**   | boolean | Do-not-call request.                  |
| `fraud`                   | **No**   | boolean | Fraud indicated or suspected.         |
| `lawSuitRisk`             | **No**   | boolean | Lawsuit or legal risk surfaced.       |
| `legalAction`             | **No**   | boolean | Legal action mentioned or threatened. |

#### Preference

| Field                 | Required | Type    | Definition                            |
| --------------------- | -------- | ------- | ------------------------------------- |
| `callbackConsent`     | **No**   | boolean | Explicit consent to future callbacks. |
| `emailOnlyPreference` | **No**   | boolean | Email-only contact preference.        |
| `wantsCallBack`       | **No**   | boolean | Wants a callback.                     |

#### Payments & Plans

| Field                 | Required | Type    | Definition                                                                                    |
| --------------------- | -------- | ------- | --------------------------------------------------------------------------------------------- |
| `cardDetailsProvided` | **No**   | boolean | Card details were given on the call.                                                          |
| `paymentFailed`       | **No**   | boolean | Payment attempt failed.                                                                       |
| `paymentMade`         | **No**   | boolean | Payment succeeded.                                                                            |
| `plan_accepted`       | **No**   | boolean | Payment plan accepted.                                                                        |
| `plan_type`           | **No**   | string  | Plan kind: `pay_in_full`, `settle_today`, `settlement_plan`, `regular_plan`, `tailored_plan`. |
| `promiseToPayDays`    | **No**   | number  | Days until promised payment.                                                                  |

#### Employment

| Field          | Required | Type    | Definition               |
| -------------- | -------- | ------- | ------------------------ |
| `isEmployed`   | **No**   | boolean | Employed.                |
| `isUnemployed` | **No**   | boolean | Unemployed.              |
| `multipleJobs` | **No**   | boolean | Multiple jobs indicated. |

#### Call progress

| Field                   | Required | Type    | Definition                               |
| ----------------------- | -------- | ------- | ---------------------------------------- |
| `attemptedVerification` | **No**   | boolean | Identity verification was attempted.     |
| `debtMentioned`         | **No**   | boolean | Debt was mentioned in the flow.          |
| `mirandaRead`           | **No**   | boolean | Miranda (or equivalent) disclosure read. |
| `offeredPaymentOptions` | **No**   | boolean | Payment options were offered.            |

#### Legal

| Field                      | Required | Type    | Definition                                        |
| -------------------------- | -------- | ------- | ------------------------------------------------- |
| `bankruptcy`               | **No**   | boolean | Bankruptcy mentioned or claimed.                  |
| `bankruptcyAttorneyName`   | **No**   | string  | Bankruptcy attorney name, if provided.            |
| `bankruptcyAttorneyPhone`  | **No**   | string  | Bankruptcy attorney phone, if provided.           |
| `bankruptcyCaseNumber`     | **No**   | string  | Bankruptcy case number, if provided.              |
| `bankruptcyChapter`        | **No**   | string  | Bankruptcy chapter, if provided.                  |
| `bankruptcyFilingDate`     | **No**   | string  | Bankruptcy filing date, if provided.              |
| `claimsPaidDirect`         | **No**   | boolean | Claims payment was made directly to the creditor. |
| `coDebtorRefused`          | **No**   | boolean | Co-debtor refused to pay or engage.               |
| `debtConsolidation`        | **No**   | boolean | Debt consolidation in play or discussed.          |
| `debtConsolidationCompany` | **No**   | string  | Named debt consolidation company.                 |
| `deployed`                 | **No**   | boolean | Military deployment indicated.                    |
| `hospitalized`             | **No**   | boolean | Hospitalization indicated.                        |
| `jail`                     | **No**   | boolean | Incarceration indicated.                          |

Future API versions may add keys; treat unexpected keys as forward-compatible.

## Fetching `recordingUrl`

When `recordingUrl` is present in the payload, it points to an authenticated endpoint on Cora's API of the form:

```text theme={null}
https://api.corafone.com/calls/<callId>/recording
```

The endpoint streams the audio file (typically `audio/mpeg`) and supports HTTP `Range` requests for seeking. **The URL is not publicly accessible** — opening it directly in a browser will return `401 Authentication required`. You must include the headers below on every `GET`.

### Required headers

| Header         | Value                                                                 |
| -------------- | --------------------------------------------------------------------- |
| `X-User-Email` | Email of an organization member on the same organization as the call. |
| `X-API-Key`    | The API key associated with that user.                                |

### Org isolation

The user identified by `X-User-Email` must belong to the same organization as the call (the same `organization.id` from the webhook envelope). Cross-organization access is rejected with `403`.

### Example — curl

```bash theme={null}
curl -L \
  -H "X-User-Email: integration@yourcompany.com" \
  -H "X-API-Key: <your_api_key>" \
  -o recording.mp3 \
  "https://api.corafone.com/calls/67a0f74d1c2e8a12f9130ae2/recording"
```

### Response codes

| Status | Meaning                                                                                     |
| ------ | ------------------------------------------------------------------------------------------- |
| `200`  | Audio stream returned.                                                                      |
| `206`  | Partial content returned (when a `Range` header is sent).                                   |
| `401`  | Missing or invalid credentials.                                                             |
| `403`  | The authenticated user does not belong to the call's organization.                          |
| `404`  | Recording is not available for this call (e.g. not yet uploaded, or no recording was made). |
| `502`  | Upstream recording fetch failed; safe to retry later.                                       |

### Operational notes

* `recordingUrl` is omitted from the payload when no recording exists for the call. Treat the field as optional.
* The URL is stable for the lifetime of the recording — you can store it and re-fetch later as long as the recording is retained.
* If you need the recording available to a non-authenticated consumer (for example, to embed in another tool), download it server-side first using the headers above and re-host it from your side.
* Native HTML `<audio>` elements cannot send custom headers. To play the recording in a browser, fetch it with the headers above, convert the response to a blob, and assign the blob URL to the `<audio>` element's `src`.

## Examples

The HTTP `POST` body is the [standard envelope](/webhooks): top-level `event`, `eventCategory`, `organization`, optional `agent`, `timestamp`, `idempotencyKey`, and nested `payload`. The **`payload`** object for `call.completed` is what the tables above describe. Below, **inner payload** means that nested `payload` only; **full body** shows the complete JSON your endpoint receives.

### Inner payload — minimal

Nothing detected in analysis beyond completion: `outcomes` is an empty object. `fileNumber` is omitted when not available. `phoneNumber` is omitted here because no valid E.164 number was available — the field is only included when a full, valid number is present, and is never sent as a partial or invalid value. `direction` is omitted here to show the unknown case, where Cora could not resolve the agent config. No recording was produced, so `recordingUrl` is omitted.

```json theme={null}
{
  "callId": "67a0f74d1c2e8a12f9130ae2",
  "status": "Completed",
  "duration": 0,
  "isTestCall": false,
  "outcomes": {},
  "summary": "",
  "createdAt": "2026-02-17T17:00:01.000Z",
  "endedAt": "2026-02-17T17:05:12.430Z"
}
```

### Inner payload — payment and plan

Typical successful contact with payment taken and a plan type discussed (not every boolean needs to be present; sparse keys only). `recordingUrl` is included — fetch it with the headers documented in [Fetching `recordingUrl`](#fetching-recordingurl).

```json theme={null}
{
  "callId": "67a0f74d1c2e8a12f9130ae2",
  "phoneNumber": "+15125550123",
  "fileNumber": "ACC-429795",
  "status": "Completed",
  "duration": 180000,
  "direction": "OUTBOUND",
  "isTestCall": false,
  "outcomes": {
    "confirmedName": true,
    "wasTheRightNumber": true,
    "wasTheRightParty": true,
    "paymentMade": true,
    "plan_accepted": true,
    "plan_type": "regular_plan",
    "promiseToPayDays": 14,
    "wantsCallBack": false
  },
  "summary": "Customer agreed to make payment on the existing plan terms.",
  "recordingUrl": "https://api.corafone.com/calls/67a0f74d1c2e8a12f9130ae2/recording",
  "createdAt": "2026-02-17T17:00:01.000Z",
  "endedAt": "2026-02-17T17:03:01.000Z"
}
```

### Inner payload — compliance and preferences

Caller requests regulatory-style limits and states contact preferences.

```json theme={null}
{
  "callId": "6812ab3c4d5e6f7089012345",
  "phoneNumber": "+13105550199",
  "fileNumber": "FILE-8821",
  "status": "Completed",
  "duration": 420000,
  "direction": "INBOUND",
  "isTestCall": false,
  "outcomes": {
    "confirmedName": true,
    "wasTheRightParty": true,
    "ceaseAndDesist": true,
    "doNotCall": true,
    "lawSuitRisk": false,
    "legalAction": false,
    "emailOnlyPreference": true,
    "wantsCallBack": false,
    "callbackConsent": false
  },
  "summary": "Consumer requested written communications only and no further calls.",
  "recordingUrl": "https://api.corafone.com/calls/6812ab3c4d5e6f7089012345/recording",
  "createdAt": "2026-03-01T14:22:00.000Z",
  "endedAt": "2026-03-01T14:29:00.000Z"
}
```

### Inner payload — wrong party / reachability

Analysis indicates the wrong person or number; collection outcomes may still be sparse.

```json theme={null}
{
  "callId": "68f0e1d2c3b4a59687012345",
  "phoneNumber": "+14085550100",
  "status": "Completed",
  "duration": 95000,
  "direction": "INBOUND",
  "isTestCall": false,
  "outcomes": {
    "wasWrongParty": true,
    "wasTheRightNumber": false,
    "refuseToPay": false
  },
  "summary": "Third party answered; debtor not available.",
  "recordingUrl": "https://api.corafone.com/calls/68f0e1d2c3b4a59687012345/recording",
  "createdAt": "2026-03-10T18:00:00.000Z",
  "endedAt": "2026-03-10T18:01:35.000Z"
}
```

### Inner payload — bankruptcy strings

When bankruptcy details are captured, related string fields may appear together with `bankruptcy: true`.

```json theme={null}
{
  "callId": "6901a2b3c4d5e6f708901234",
  "phoneNumber": "+12125550111",
  "fileNumber": "BNK-10044",
  "status": "Completed",
  "duration": 310000,
  "direction": "OUTBOUND",
  "isTestCall": false,
  "outcomes": {
    "confirmedName": true,
    "wasTheRightParty": true,
    "bankruptcy": true,
    "bankruptcyChapter": "13",
    "bankruptcyCaseNumber": "25-12345-ABC",
    "bankruptcyFilingDate": "2025-11-01",
    "bankruptcyAttorneyName": "Jane Doe Law Firm",
    "bankruptcyAttorneyPhone": "+13125559876",
    "paymentMade": false,
    "plan_accepted": false
  },
  "summary": "Debtor stated active Chapter 13; case and attorney details provided.",
  "recordingUrl": "https://api.corafone.com/calls/6901a2b3c4d5e6f708901234/recording",
  "createdAt": "2026-03-12T16:10:00.000Z",
  "endedAt": "2026-03-12T16:15:10.000Z"
}
```

### Inner payload — payment failed on call

A payment was attempted but did not succeed; `paymentMade` may be false or omitted.

```json theme={null}
{
  "callId": "6902c3d4e5f6071829345678",
  "phoneNumber": "+15125550900",
  "fileNumber": "ACC-10002",
  "status": "Completed",
  "duration": 240000,
  "direction": "OUTBOUND",
  "isTestCall": false,
  "outcomes": {
    "confirmedName": true,
    "wasTheRightParty": true,
    "cardDetailsProvided": true,
    "paymentFailed": true,
    "paymentMade": false,
    "wantedToTalkHuman": true
  },
  "summary": "Card declined; customer will call back with another card.",
  "recordingUrl": "https://api.corafone.com/calls/6902c3d4e5f6071829345678/recording",
  "createdAt": "2026-03-12T20:00:00.000Z",
  "endedAt": "2026-03-12T20:04:00.000Z"
}
```

### Full HTTP body (envelope + inner payload)

What your server receives for `call.completed` when an agent is associated with the call. If the webhook is organization-only, `agent` is omitted. `idempotencyKey` is stable per organization and `callId` for this event.

```json theme={null}
{
  "event": "call.completed",
  "eventCategory": "calls",
  "idempotencyKey": "call.completed:507f1f77bcf86cd799439011:67a0f74d1c2e8a12f9130ae2",
  "organization": {
    "id": "507f1f77bcf86cd799439011",
    "name": "Acme Corp"
  },
  "agent": {
    "id": "507f191e810c19729de860ea",
    "name": "Outbound Collections"
  },
  "timestamp": "2026-02-17T17:03:01.000Z",
  "payload": {
    "callId": "67a0f74d1c2e8a12f9130ae2",
    "phoneNumber": "+15125550123",
    "fileNumber": "ACC-429795",
    "status": "Completed",
    "duration": 180000,
    "direction": "OUTBOUND",
    "isTestCall": false,
    "outcomes": {
      "confirmedName": true,
      "wasTheRightParty": true,
      "paymentMade": true,
      "plan_accepted": true,
      "plan_type": "regular_plan"
    },
    "summary": "Customer agreed to make payment.",
    "recordingUrl": "https://api.corafone.com/calls/67a0f74d1c2e8a12f9130ae2/recording",
    "createdAt": "2026-02-17T17:00:01.000Z",
    "endedAt": "2026-02-17T17:03:01.000Z"
  }
}
```
