Skip to main content

Webhooks

A webhook endpoint receives one event type, Call started or Call ended, at a URL you choose. Add endpoints in Settings > Developers, or create and delete them through the API as shown below. The Webhooks section of the API reference describes each event's payload, delivery, and retries.

Creating and deleting endpoints needs a key whose user is an Admin or a Member of the Account. A Viewer's key gets 403.

1. Create an endpoint​

curl https://api.harmony.ai/api/v1/webhooks \
-H "Authorization: Bearer $HARMONY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/harmony/calls",
"eventType": "call_ended",
"description": "CRM sync",
"enabled": true
}'
  • url must use HTTPS. Harmony never delivers to a private network address.
  • Send enabled: true to receive events right away. Without it, the endpoint starts disabled and receives only the test events you send from Settings. Enable it later in Settings, or delete it and create it again.
  • Add "filters": { "agentId": "<agent id>" } to receive only one agent's calls. Leave it out to receive every agent's calls.

Harmony answers 201 Created with the endpoint and its signing secret:

{
"endpoint": {
"id": "0196f0a4-2b7c-7d10-9e3f-4a5b6c7d8e9f",
"eventType": "call_ended",
"url": "https://example.com/harmony/calls",
"description": "CRM sync",
"enabled": true,
"filters": {}
},
"secret": "whsec_..."
}

The secret is shown only in this response. Store it with the endpoint's id: you need the secret to verify events and the id to delete the endpoint. Responses contain more fields than shown here; the API reference documents all of them.

A request Harmony can't accept gets 400, and code says why:

  • invalid_input: the body doesn't match the schema, for example a malformed or too long url.
  • invalid_url: the URL doesn't use HTTPS or contains a user name or password.
  • blocked_destination: the URL's host is a private IP address.
  • agent_not_found: filters.agentId names no agent in your Account.

2. Verify each event​

Harmony signs every event with the Standard Webhooks scheme. Verify the raw request body and the webhook-id, webhook-timestamp, and webhook-signature headers with the secret before you trust the event:

import { Webhook } from "standardwebhooks";

const event = new Webhook(secret).verify(rawBody, headers);

verify throws when the signature is wrong or the timestamp is more than five minutes from now. Answer with a non-2xx status in that case. Retries keep the same webhook-id, so deduplicate by it.

3. Delete the endpoint​

curl -X DELETE https://api.harmony.ai/api/v1/webhooks/0196f0a4-2b7c-7d10-9e3f-4a5b6c7d8e9f \
-H "Authorization: Bearer $HARMONY_API_KEY"

Harmony answers 204 No Content. Don't send a Content-Type: application/json header without a body: Harmony rejects that request with 400.