---
title: "Call ended event"
method: POST
path: "call.ended"
tags: ["Webhook Events"]
---

# Call ended event

`POST call.ended` (webhook)

Fired on call hangup with the duration and a zero-markup billing
breakdown (Meta cost, Telnyx cost, recording surcharge, total).
Costs are pass-through; no margin is applied.

## Payload

- WebhookPayloadCallEnded — Webhook payload for the `call.ended` event. Fires on call hangup with the duration and a zero-markup billing breakdown.
  - `id` string, required
  - `event` 'call.ended', required
  - `call` object, required
    - `id` string
    - `metaCallId` string, nullable
    - `accountId` string
    - `phoneNumberId` string
    - `direction` 'inbound' | 'outbound'
    - `from` string
    - `to` string
    - `startedAt` string, date-time
    - `endedAt` string, date-time
    - `durationSeconds` integer
    - `endReason` 'hangup' | 'no_answer' | 'rejected' | 'error'
    - `recordingUrl` string
    - `recordingExpiresAt` string, date-time
    - `billing` object
      - `metaCostUSD` number — Meta per-minute charge. Billed by Meta DIRECTLY to your WhatsApp Business Account payment method (your separate Meta invoice). Zernio does NOT charge this. Display only.
      - `telnyxCostUSD` number
      - `recordingCostUSD` number
      - `billableCostUSD` number — The amount Zernio bills you = Telnyx leg + recording. Excludes Meta (billed by Meta directly).
      - `totalCostUSD` number — Full economic cost incl. the Meta portion you pay directly (Meta + Telnyx + recording). Display only, not the Zernio-billed amount.
  - `account` InboxWebhookAccount, required — The account context included in inbox webhook payloads.
    - `id` string, required — Social account ID
    - `accountId` string — Social account ID (same value as id). Canonical field so consumers can filter every webhook event on one field (e.g. route staging vs production by account). id is kept for backward compatibility.
    - `profileId` string — Zernio profile (workspace) ID this account belongs to. Use it to route or filter inbox webhooks by workspace. This is the profile ID only, not its name (resolve the name via the API with this ID). Optional; omitted on the shared WhatsApp sandbox account and when the account has no resolvable profile.
    - `platform` string, required
    - `username` string, required
    - `displayName` string
  - `timestamp` string, date-time, required

## Acknowledgement `200`

Webhook received successfully

---

[API](https://skmtc.net/zernio/apis/zernio-api.md) · [All operations](https://skmtc.net/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/zernio/zernio-api/versions/51932b099b2f/schema)
