---
updatedAt: 2026-10-15T02:11:01.000Z
agentTools:
  projectIndex: https://developer.mixmax.com/llms.txt
---

# /calls/:id/transcript [beta]

**Limited beta.** The Calls read API is currently gated by an access allowlist; callers without access receive `404` responses. To request access, email [developer@mixmax.com](mailto:developer@mixmax.com).

Returns the transcript of a completed call. Requires the Dialer `calling` feature on your workspace, and transcription must be enabled for the workspace. By default you read your own calls; workspace admins can pass `scope=workspace` to read any member's. Managed API keys require the `calls:read` permission.

When transcription is complete, `turns` holds the normalized, time-ordered speaker turns. While it is still in progress or if it failed, `turns` is empty and `status` reflects the state. Responses are private to the caller and must not be cached.

# OpenAPI definition

````json
{
  "openapi": "3.1.0",
  "info": {
    "title": "API endpoints",
    "version": "1.0",
    "description": "The Mixmax REST API, optimized for lightweight, real-time interactions. This specification is the source of truth for the definition-backed API reference on developer.mixmax.com: it lives in the api repository (openapi/openapi.yaml) and is published from CI.",
    "contact": {
      "email": "developer@mixmax.com"
    }
  },
  "servers": [
    {
      "url": "https://api.mixmax.com"
    }
  ],
  "components": {
    "securitySchemes": {
      "sec0": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Token",
        "x-default": "yourkey"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "description": "Human-readable description of the error."
          }
        }
      },
      "CallRecordingAvailableEvent": {
        "type": "object",
        "description": "The JSON body of a `call:recording-available` webhook delivery. It identifies the call and nothing more: no audio, phone numbers, names, email addresses, transcript text or telephony provider links. Mixmax may add fields later, so ignore fields you do not recognize.",
        "required": [
          "eventName",
          "eventId",
          "callId",
          "userId",
          "recordingStartedAt",
          "recordingDurationSeconds",
          "occurredAt",
          "recordingUrl"
        ],
        "properties": {
          "eventName": {
            "type": "string",
            "enum": [
              "call:recording-available"
            ],
            "description": "The event type. Always `call:recording-available`."
          },
          "eventId": {
            "type": "string",
            "description": "Identifies the event. Every copy of the same event carries the same `eventId`, including retries and duplicates, so use it to skip events you have already processed. Treat it as an opaque string."
          },
          "callId": {
            "type": "string",
            "description": "The call's `_id`, the same value `GET /v1/calls` returns. Pass it to `GET /v1/calls/{id}/recording`."
          },
          "userId": {
            "type": "string",
            "description": "The Mixmax user who placed the call."
          },
          "workspaceId": {
            "type": "string",
            "description": "The Mixmax workspace the call belongs to. Absent on some calls, so do not depend on it."
          },
          "recordingStartedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the recording started, in ISO 8601 (UTC)."
          },
          "recordingDurationSeconds": {
            "type": "integer",
            "minimum": 0,
            "description": "Length of the recording, in whole seconds."
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time",
            "description": "When Mixmax learned that the recording was complete, in ISO 8601 (UTC)."
          },
          "recordingUrl": {
            "type": "string",
            "format": "uri",
            "description": "Where to download the audio: always `https://api.mixmax.com/v1/calls/{callId}/recording`, a Mixmax API endpoint, never a direct media link. Request it with your API token in the `X-API-Token` header; it does not work without one. An API key made on **Admin center > API keys** needs the **Read calls** (`calls:read`) permission. It returns the whole MP3 file; byte-range requests are not supported, so download it once."
          },
          "test": {
            "type": "boolean",
            "description": "`true` only on the sample event that **Send test event** posts. Real deliveries do not include this field."
          }
        }
      },
      "CallActivityEvent": {
        "type": "object",
        "description": "The JSON body that a rule's **Post to webhook** action sends for the `call:started` and `call:completed` triggers. If the action defines a custom payload, Mixmax sends that instead and does not add `eventName`. Unlike `call:recording-available`, this body includes the phone number that was called and, when known, the name and email address of the person called. Mixmax may add fields later, so ignore fields you do not recognize.",
        "required": [
          "eventName",
          "userId"
        ],
        "properties": {
          "eventName": {
            "type": "string",
            "enum": [
              "call:started",
              "call:completed"
            ],
            "description": "The event type."
          },
          "callId": {
            "type": "string",
            "description": "**New.** The call's `_id`, the same value `GET /v1/calls` returns and the same `callId` as in the `call:recording-available` webhook. Use it to match the events of one call and to download its recording with `GET /v1/calls/{id}/recording`."
          },
          "userId": {
            "type": "string",
            "description": "The Mixmax user who placed the call."
          },
          "created": {
            "type": "integer",
            "format": "int64",
            "description": "When the call record was created, in epoch milliseconds."
          },
          "fromPhoneNumber": {
            "type": "object",
            "description": "The Mixmax number the call was placed from.",
            "properties": {
              "phoneNumber": {
                "type": "string",
                "description": "The number, in E.164 format."
              },
              "friendlyName": {
                "type": "string",
                "description": "The number, formatted for display."
              }
            }
          },
          "phoneNumber": {
            "type": "string",
            "description": "The number that was called."
          },
          "email": {
            "type": "string",
            "description": "Email address of the person called, when known."
          },
          "fullName": {
            "type": "string",
            "description": "Name of the person called, when known."
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the call was dialed."
          },
          "completedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the call ended. Only on `call:completed`."
          }
        }
      }
    },
    "parameters": {
      "MixmaxSignatureHeader": {
        "name": "X-Mixmax-Signature",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "v1,97yqJFN2Tx0WlGgkygjuwQaZHhjsIy1E+eP6ejjShHk=",
        "description": "`v1,` followed by the base64-encoded HMAC-SHA256 of `<X-Mixmax-Webhook-Id>.<X-Mixmax-Timestamp>.<raw request body>`, keyed with your signing secret. Verify it before you trust the body."
      },
      "MixmaxTimestampHeader": {
        "name": "X-Mixmax-Timestamp",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "1791468381",
        "description": "When Mixmax signed this delivery attempt, in Unix seconds. It is part of the signed content. Reject a delivery whose timestamp is more than 5 minutes away from your clock."
      },
      "MixmaxWebhookIdHeader": {
        "name": "X-Mixmax-Webhook-Id",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        },
        "example": "00000000-0000-4000-8000-000000000000",
        "description": "A new UUID for every delivery attempt, including each retry. It is part of the signed content. Do not use it to detect duplicates; each webhook's description says what to use."
      }
    }
  },
  "security": [
    {
      "sec0": []
    }
  ],
  "tags": [
    {
      "name": "Calls"
    }
  ],
  "paths": {
    "/v1/calls/{id}/transcript": {
      "get": {
        "summary": "/calls/:id/transcript [beta]",
        "description": "**Limited beta.** The Calls read API is currently gated by an access allowlist; callers without access receive `404` responses. To request access, email [developer@mixmax.com](mailto:developer@mixmax.com).\n\nReturns the transcript of a completed call. Requires the Dialer `calling` feature on your workspace, and transcription must be enabled for the workspace. By default you read your own calls; workspace admins can pass `scope=workspace` to read any member's. Managed API keys require the `calls:read` permission.\n\nWhen transcription is complete, `turns` holds the normalized, time-ordered speaker turns. While it is still in progress or if it failed, `turns` is empty and `status` reflects the state. Responses are private to the caller and must not be cached.",
        "operationId": "getcalltranscript",
        "tags": [
          "Calls"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The call `_id`, from `GET /calls`."
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "workspace"
              ]
            },
            "description": "Pass `workspace` to read a workspace member's transcript. Requires workspace admin access; other callers receive a `403`."
          }
        ],
        "responses": {
          "200": {
            "description": "The call's transcript. `turns` is populated only when `status` is `completed`; for `queued` or `failed` it is an empty array.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "callId": {
                      "type": "string",
                      "description": "The call `_id` this transcript belongs to."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "completed",
                        "failed"
                      ],
                      "description": "Transcription lifecycle state."
                    },
                    "turns": {
                      "type": "array",
                      "description": "Normalized transcript turns, in spoken order. Empty until completed.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Speaker label for the turn (for example `Speaker 0`)."
                          },
                          "message": {
                            "type": "string",
                            "description": "The spoken text of the turn."
                          },
                          "timestamp": {
                            "type": "number",
                            "description": "Offset of the turn from the start of the recording, in seconds."
                          }
                        }
                      }
                    },
                    "languageCode": {
                      "type": "string",
                      "description": "BCP-47 language detected for the transcript (for example `en-US`)."
                    },
                    "recordingSid": {
                      "type": "string",
                      "description": "Identifier of the source recording with the telephony provider."
                    },
                    "transcriptionId": {
                      "type": "string",
                      "description": "Identifier of the transcription with the telephony provider."
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "Completed": {
                    "value": {
                      "callId": "5f3e8a1b2c4d6e7f8a9b0c1d",
                      "status": "completed",
                      "languageCode": "en-US",
                      "recordingSid": "RE0123456789abcdef0123456789abcdef",
                      "transcriptionId": "voice_transcription_7n7hnd7sf68yfv5re42nvvz7aa",
                      "turns": [
                        {
                          "name": "Speaker 0",
                          "message": "Hi, this is Alex from Mixmax.",
                          "timestamp": 0.5
                        },
                        {
                          "name": "Speaker 1",
                          "message": "Hi Alex, thanks for calling.",
                          "timestamp": 3.1
                        }
                      ],
                      "createdAt": "2026-08-04T17:25:00.000Z",
                      "updatedAt": "2026-08-04T17:25:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Returned in three cases: `scope=workspace` was requested without workspace admin access (JSON body), a managed API key was used without the `calls:read` permission or outside the workspace it was made in (JSON body), or the workspace does not have the Dialer `calling` feature (empty body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The call does not exist, has no transcript, or the caller does not have access to the Calls API beta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "deprecated": false,
        "x-readme": {
          "code-samples": [
            {
              "language": "curl",
              "code": "curl -v --header \"X-API-Token: <your token>\" \"https://api.mixmax.com/v1/calls/<call id>/transcript\""
            }
          ],
          "samples-languages": [
            "curl"
          ]
        }
      }
    }
  },
  "webhooks": {
    "callRecordingAvailable": {
      "post": {
        "summary": "call:recording-available [beta]",
        "operationId": "callRecordingAvailableWebhook",
        "tags": [
          "Calls"
        ],
        "description": "**Limited beta.** This webhook is available to workspaces in the Calls API limited beta,\nbecause the recording it announces is downloaded with `GET /v1/calls/{id}/recording`, which\nis part of that beta. To request access, email\n[developer@mixmax.com](mailto:developer@mixmax.com).\n\nMixmax sends this `POST` to your endpoint when the recording of a call placed with the\nMixmax Dialer is ready to download. The body identifies the call and nothing more: no audio,\nphone numbers, names, email addresses or transcript text. Download the audio from\n`recordingUrl` with your API token.\n\n### Register your endpoint\n\nWorkspace admins register the endpoint in the Mixmax app:\n\n1. Open **Admin center > API keys** (`https://app.mixmax.com/dashboard/admin/api-tokens`)\n   and find the **Webhooks** section.\n2. Enter your endpoint URL and select **Call recording available** under **Events**.\n3. Copy the signing secret and store it with your receiver. You need it to verify\n   deliveries. Mixmax shows the secret only once; afterwards the page shows its last four\n   characters. If you lose it, regenerate it.\n4. Click **Save**, then **Send test event** to check that your endpoint receives and\n   verifies a delivery.\n\nEach workspace has one webhook URL. It receives this event for the recorded calls of every\nmember of the workspace. Mixmax sends nothing until a URL is saved, and it does not send\nevents for recordings that were ready before then. To stop deliveries, remove the URL: this\ndeletes the webhook, and saving a URL again sets it up afresh. The\nwebhook is managed only on this page; it does not appear among your rules.\n\n### When it is sent\n\nOnce per recorded call, usually within a few minutes of the call ending, when all of these\nare true:\n\n- The call was placed with the Mixmax Dialer by a member of your workspace.\n- The call was recorded: recording was on and allowed for the call, and the call was\n  answered.\n- The recording completed successfully.\n\nIt is not sent for calls that were not recorded, for recordings that failed, or for\nrecordings that were ready before your URL was saved. Mixmax sends no event when a recording\nis later deleted or expires.\n\n### Download the recording\n\n`recordingUrl` is always `https://api.mixmax.com/v1/calls/{callId}/recording`. Request it\nwith an API token in the `X-API-Token` header. An API key made on **Admin center > API\nkeys** needs the **Read calls** (`calls:read`) permission; without it the request is\nrefused with a `403`. A member's token downloads only that member's own calls. To download a\ncall placed by someone else in the workspace, use a token that acts for a workspace admin\nand add `?scope=workspace`. The endpoint allows 20 requests per minute per user.\n\nRecordings are not kept forever, so download and store the audio soon after you receive the\nevent. A `404` means the recording is no longer available, or that your workspace is not in\nthe Calls API beta.\n\n### Delivery\n\n- **Request.** A JSON `POST` with `Content-Type: application/json`. Mixmax waits up to 30\n  seconds for a response. Reply with any `2xx` status as soon as you have stored the event,\n  and do the work afterwards. The response body is ignored.\n- **At least once.** The same event can arrive more than once, for example when a delivery\n  is retried after a timeout. Every copy carries the same `eventId`: record the ids you have\n  processed and skip repeats. Do not use `X-Mixmax-Webhook-Id` for this, because it changes\n  on every attempt.\n- **No ordering.** Events arrive in no particular order. This event often arrives before the\n  `call:completed` webhook for the same call.\n- **Retries.** If your endpoint times out, cannot be reached, or replies with a status other\n  than `2xx` or `404`, Mixmax retries about every 5 minutes, a limited number of times. If\n  the last attempt fails, Mixmax pauses the webhook and emails your workspace admins.\n- **A `404` pauses at once.** Mixmax reads a `404` reply as \"this URL no longer exists\": it\n  pauses the webhook without retrying and emails your workspace admins.\n\nAfter fixing your endpoint, turn the webhook back on in the **Webhooks** section.\n\n### Verify the signature\n\nEvery delivery from a webhook action that has a signing secret is signed with it. The\nsecret starts with `whsec_`.\nCheck the signature before you trust the body:\n\n1. Read the raw request body exactly as received, before parsing the JSON.\n2. Join `X-Mixmax-Webhook-Id`, `X-Mixmax-Timestamp` and the raw body, with a `.` between\n   each.\n3. Remove the `whsec_` prefix from the secret and base64-decode the rest. The result is the\n   HMAC key.\n4. Compute the HMAC-SHA256 of the joined string with that key, and base64-encode it.\n5. `X-Mixmax-Signature` is `v1,` followed by that value. Compare the two with a\n   constant-time comparison.\n6. Reject the delivery if `X-Mixmax-Timestamp` (Unix seconds) is more than 5 minutes away\n   from your clock. This blocks replayed deliveries.\n\nIn Node.js:\n\n```js\nconst crypto = require('crypto');\n\n// rawBody: the request body as a Buffer, before JSON parsing.\nfunction verifyMixmaxSignature({ rawBody, headers, secret }) {\n  const id = headers['x-mixmax-webhook-id'];\n  const timestamp = headers['x-mixmax-timestamp'];\n  const signature = headers['x-mixmax-signature'] || '';\n  if (!id || !timestamp || !signature.startsWith('v1,')) return false;\n  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 5 * 60) return false;\n  const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64');\n  const expected = crypto\n    .createHmac('sha256', key)\n    .update(`${id}.${timestamp}.`)\n    .update(rawBody)\n    .digest();\n  const received = Buffer.from(signature.slice(3), 'base64');\n  return received.length === expected.length && crypto.timingSafeEqual(received, expected);\n}\n```\n\nTo test your code, use these placeholder inputs (not a real secret) and skip the timestamp\ncheck. They must produce the signature\n`v1,97yqJFN2Tx0WlGgkygjuwQaZHhjsIy1E+eP6ejjShHk=`.\n\n- Secret: `whsec_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=`\n- `X-Mixmax-Webhook-Id`: `00000000-0000-4000-8000-000000000000`\n- `X-Mixmax-Timestamp`: `1791468381`\n- Raw body, on one line with no trailing newline:\n\n```json\n{\"eventName\":\"call:recording-available\",\"eventId\":\"65f000000000000000000001:recording-available\",\"callId\":\"65f000000000000000000001\",\"userId\":\"65f000000000000000000002\",\"workspaceId\":\"65f000000000000000000003\",\"recordingStartedAt\":\"2026-10-08T14:03:11.000Z\",\"recordingDurationSeconds\":184,\"occurredAt\":\"2026-10-08T14:06:20.412Z\",\"recordingUrl\":\"https://api.mixmax.com/v1/calls/65f000000000000000000001/recording\"}\n```\n\nWhen an admin regenerates the signing secret, the next delivery is signed with the new\nsecret. Update your receiver right away; until you do, deliveries fail verification.\n\n### Test events\n\n**Send test event** posts one sample event to your endpoint, signed with your secret like a\nreal delivery. It has `\"test\": true` and placeholder ids, holds no real call data, and its\n`recordingUrl` does not lead to a recording. Reply to it with a `2xx` and do not process it\nfurther.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MixmaxSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/MixmaxTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/MixmaxWebhookIdHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CallRecordingAvailableEvent"
              },
              "examples": {
                "Delivery": {
                  "value": {
                    "eventName": "call:recording-available",
                    "eventId": "65f000000000000000000001:recording-available",
                    "callId": "65f000000000000000000001",
                    "userId": "65f000000000000000000002",
                    "workspaceId": "65f000000000000000000003",
                    "recordingStartedAt": "2026-10-08T14:03:11.000Z",
                    "recordingDurationSeconds": 184,
                    "occurredAt": "2026-10-08T14:06:20.412Z",
                    "recordingUrl": "https://api.mixmax.com/v1/calls/65f000000000000000000001/recording"
                  }
                },
                "Test event": {
                  "value": {
                    "eventName": "call:recording-available",
                    "eventId": "000000000000000000000000:recording-available",
                    "callId": "000000000000000000000000",
                    "userId": "000000000000000000000000",
                    "recordingStartedAt": "2026-10-08T14:03:11.000Z",
                    "recordingDurationSeconds": 0,
                    "occurredAt": "2026-10-08T14:06:20.412Z",
                    "recordingUrl": "https://api.mixmax.com/v1/calls/000000000000000000000000/recording",
                    "test": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any `2xx` status, sent within 30 seconds, acknowledges the delivery. The response body is ignored."
          },
          "404": {
            "description": "Read as \"this URL no longer exists\". Mixmax pauses the webhook at once, without retrying, and emails your workspace admins."
          },
          "default": {
            "description": "Any other status, no response within 30 seconds, or a connection error. Mixmax retries about every 5 minutes, a limited number of times, and pauses the webhook if the last attempt fails."
          }
        },
        "security": []
      }
    },
    "callStarted": {
      "post": {
        "summary": "call:started",
        "operationId": "callStartedWebhook",
        "tags": [
          "Calls"
        ],
        "description": "Sent by a rule with the **I start a call** trigger (or its workspace rule equivalent) and a\n**Post to webhook** action, each time a call is dialed with the Mixmax Dialer. Create the\nrule under **Rules** in the Mixmax app.\n\n**New:** the body now includes `callId`, the call's `_id`. Use it to match this event to\n`call:completed`, to `call:recording-available` and to `GET /v1/calls`.\n\nDeliveries are signed, retried and paused the same way as the `call:recording-available`\nwebhook; that page explains how to verify `X-Mixmax-Signature`. Webhook actions saved before\nMixmax began signing deliveries have no signing secret and are sent without the\n`X-Mixmax-*` headers. To give one a secret, `PATCH` it with `rotateSigningSecret: true`\n(see `PATCH /v1/rules/{id}/actions/{actionId}`). Delivery is at least once and in no\nparticular order. This body has no event id, so skip duplicates on `callId` and\n`eventName`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MixmaxSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/MixmaxTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/MixmaxWebhookIdHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CallActivityEvent"
              },
              "examples": {
                "Delivery": {
                  "value": {
                    "eventName": "call:started",
                    "callId": "65f000000000000000000001",
                    "userId": "65f000000000000000000002",
                    "created": 1791468184512,
                    "fromPhoneNumber": {
                      "phoneNumber": "+15555550100",
                      "friendlyName": "(555) 555-0100"
                    },
                    "phoneNumber": "+15555550123",
                    "email": "contact@example.com",
                    "fullName": "Example Contact",
                    "startedAt": "2026-10-08T14:03:05.000Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any `2xx` status, sent within 30 seconds, acknowledges the delivery. The response body is ignored."
          },
          "404": {
            "description": "Read as \"this URL no longer exists\". Mixmax pauses the rule at once, without retrying, and emails its owner (the workspace admins for a workspace rule)."
          },
          "default": {
            "description": "Any other status, no response within 30 seconds, or a connection error. Mixmax retries about every 5 minutes, a limited number of times, and pauses the rule if the last attempt fails."
          }
        },
        "security": []
      }
    },
    "callCompleted": {
      "post": {
        "summary": "call:completed",
        "operationId": "callCompletedWebhook",
        "tags": [
          "Calls"
        ],
        "description": "Sent by a rule with the **I finish a call** trigger (or its workspace rule equivalent) and a\n**Post to webhook** action, each time a call placed with the Mixmax Dialer ends and is\nlogged. Create the rule under **Rules** in the Mixmax app.\n\n**New:** the body now includes `callId`, the call's `_id`. Use it to match this event to\n`call:started`, to `call:recording-available` and to `GET /v1/calls`. For a recorded call,\n`call:recording-available` often arrives before this event.\n\nDeliveries are signed, retried and paused the same way as the `call:recording-available`\nwebhook; that page explains how to verify `X-Mixmax-Signature`. Webhook actions saved before\nMixmax began signing deliveries have no signing secret and are sent without the\n`X-Mixmax-*` headers. To give one a secret, `PATCH` it with `rotateSigningSecret: true`\n(see `PATCH /v1/rules/{id}/actions/{actionId}`). Delivery is at least once and in no\nparticular order. This body has no event id, so skip duplicates on `callId` and\n`eventName`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MixmaxSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/MixmaxTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/MixmaxWebhookIdHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CallActivityEvent"
              },
              "examples": {
                "Delivery": {
                  "value": {
                    "eventName": "call:completed",
                    "callId": "65f000000000000000000001",
                    "userId": "65f000000000000000000002",
                    "created": 1791468184512,
                    "fromPhoneNumber": {
                      "phoneNumber": "+15555550100",
                      "friendlyName": "(555) 555-0100"
                    },
                    "phoneNumber": "+15555550123",
                    "email": "contact@example.com",
                    "fullName": "Example Contact",
                    "startedAt": "2026-10-08T14:03:05.000Z",
                    "completedAt": "2026-10-08T14:06:15.000Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any `2xx` status, sent within 30 seconds, acknowledges the delivery. The response body is ignored."
          },
          "404": {
            "description": "Read as \"this URL no longer exists\". Mixmax pauses the rule at once, without retrying, and emails its owner (the workspace admins for a workspace rule)."
          },
          "default": {
            "description": "Any other status, no response within 30 seconds, or a connection error. Mixmax retries about every 5 minutes, a limited number of times, and pauses the rule if the last attempt fails."
          }
        },
        "security": []
      }
    }
  },
  "x-readme": {
    "headers": [],
    "explorer-enabled": false,
    "proxy-enabled": true
  }
}
````