Skip to main content

Overview

Agents talk to your server in two ways. Both are HTTPS endpoints that you set on the agent, and 60db signs every request. Both use the same signing scheme. See Verify signatures.

Define tools

Add tools to an agent with tools. Each tool is described with JSON Schema, so the agent knows when to use it and what arguments to send.
Set the URL on the agent when you create it or later with PATCH /agents/{agentId}. A URL that is not https:// returns 400 VALIDATION_ERROR. A URL on port other than 443, one with credentials or a fragment, or one that resolves to a private or loopback address returns 422 UNSAFE_WEBHOOK_URL.

Tool call request

When the agent calls a tool, 60db sends a POST to your tool_webhook_url:

Your reply

Reply with a JSON object within about 6 seconds. The agent speaks what it needs from that object.
If your reply is late, not JSON, too large or not 2xx, the agent receives an error object instead of your reply. The call continues. Other reason values: unsafe_url (the address failed the safety check at call time). Notes:
  • No retries. A tool call is sent once. If it fails, the agent gets the error.
  • Duplicate calls. If the same tool_call_id arrives again, 60db returns the saved answer. Your endpoint is not called a second time.
  • Tool log. Every tool call is logged with its arguments, your reply, status code and latency. See the Tool log in the dashboard, or GET /agents/{agentId}/tool-events for the last 50. Logs are kept 30 days.

Example tool endpoint (Node.js)

Example tool endpoint (Python)

Call transfer

Besides webhook (JSON) tools, an agent can hand a call to a person. Set transfer_targets on the agent, or per call in overrides.transfer_targets:
How it works. The name is what callers ask for (“connect me to Sales”), so use a team name callers would say, not “Call Transfer”. The numbers are tried in turn until someone answers. The first target is also used when a caller asks for “a person”. 60db adds the matching instruction to your agent automatically; you don’t need to write it in the script.
  • Each group becomes a function the agent can use, transfer_to_<name> (Sales Team becomes transfer_to_sales_team). The agent only picks a name; the numbers stay with you.
  • The first group is used when a caller asks for a person without saying which team.
  • With several numbers in a group, they are tried in turn. If one fails or refuses, the next is tried, and the call stays with the agent if none answers.
  • Up to 10 groups of up to 10 E.164 numbers. Names must be distinct, and webhook tools cannot be named transfer_call or start with transfer_to_.
  • summary.transferred on the call says whether it was handed over. The transferred leg is billed as Dialer minutes on your line.
In the dashboard, open the agent’s Tools & webhooks tab, choose Add tool, then Call transfer.

Events

When a call ends, or its recording is ready, 60db sends an event to event_webhook_url. Events are sent only when the agent has an event_webhook_url. recording.ready is sent only for recorded calls. It can arrive after call.completed.

Envelope

Every event has the same envelope:
recording.ready carries the recording details and transcript, not a download link:
Download the audio with your API key at https://api.60db.ai{audio_path} (add ?download=1 to save it as a file).

Event headers

Retries

  • Any response other than 2xx, a timeout or a network error counts as a failed attempt. Redirects count as failures too.
  • Reply quickly. Acknowledge with 2xx before doing slow work. A reply slower than about 5 seconds counts as a timeout.
  • 60db makes up to 5 attempts. It waits 30 seconds, then 1, 2 and 4 minutes between them.
  • After the fifth failed attempt the event is marked failed and is not sent again.
  • Events can arrive more than once, for example if your response was lost. Process each X-60db-Event-Id once.
  • Events can arrive out of order. Read the call again with GET /agents/calls/{callId} if you need its current state.

Verify signatures

Verify every tool call and event before you act on it.
  • Use the secret exactly as returned (whsec_…). Use its UTF-8 bytes as the HMAC key. Do not decode it.
  • Hash the raw body bytes as received. Do not parse and re-serialise the JSON first.
  • Reject timestamps more than 300 seconds from your server’s clock.
  • Compare signatures in constant time.

Node.js

Use the SDK helper:
Or with Node’s crypto module:

Python

Use the SDK helper:
Or with the standard library:

Test with curl

curl cannot verify a signature, but you can send a signed test request to your endpoint:

Rotate the secret

The response includes a new webhook_secret. The old secret stops working at once. This covers tool calls and events, including retries that have not been sent yet. Update your server with the new secret right after you rotate. Until you do, signatures will not verify. To limit the gap, store the new value and redeploy in one step.