From 76b3bd256b068936191b610e32017f1669af9245 Mon Sep 17 00:00:00 2001 From: Jeff Hoekman Date: Tue, 8 Sep 2026 13:24:06 -0400 Subject: [PATCH 1/2] VAP15-54 docs: document subsystem server credentials Extends VAP15-53 to the webhooks that go to a subsystem's own server rather than the assistant's webhook url - tools, knowledge bases, custom voices, dynamic handoff and transfer destinations, and custom endpointing providers. The rule is provenance inheritance: a subsystem server follows the assistant carrying it. A saved assistant keeps org credentials; a transient assistant or assistantOverrides is caller-authored and gets none. Calls out the mixed case, a saved assistant with an overridden voice, tools or knowledge base. Also gives the intelligent-routing handoff example an Authorization header. It was the only dynamic-destination example teaching a bare unauthenticated server url, directly under one that has auth. That content now lives in squads/handoff/destinations.mdx, which main split out of the handoff page. Provisional: VAPSEC-627 (#19542) is unreviewed and still changing. Re-verify the table and the inheritance rule against the merged behavior before this ships. Refs VAP15-54, VAPSEC-627 Co-Authored-By: Claude Opus 5 --- fern/server-url/server-authentication.mdx | 19 +++++++++++++++++++ fern/squads/handoff/destinations.mdx | 9 ++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/fern/server-url/server-authentication.mdx b/fern/server-url/server-authentication.mdx index 1b21996aa..5d8069b44 100644 --- a/fern/server-url/server-authentication.mdx +++ b/fern/server-url/server-authentication.mdx @@ -405,6 +405,25 @@ If you supply the server URL in your API request, your endpoint must authenticat For webhooks sent to a server URL supplied in the API request, Vapi also strips credential fields from the payload. Any `apiKey`, `secret`, `password`, `authToken`, or similar field on the embedded `assistant`, `session`, or `chat` object arrives as the string `"[REDACTED]"` rather than its real value. The rest of the payload is unchanged. +#### Subsystem server URLs + +Some webhooks go to a URL owned by a subsystem rather than to your assistant's webhook URL - a tool, a knowledge base, a custom voice, a dynamic handoff or transfer destination, or a custom endpointing provider each carry their own `server` block: + +| Webhook | Server it is sent to | +| --- | --- | +| `tool-calls`, `function-call` | the tool's | +| `knowledge-base-request` | the knowledge base's | +| `voice-request` | the custom voice's | +| `handoff-destination-request` | the handoff destination's | +| `transfer-destination-request` | the transfer destination's | +| `call.endpointing.request` | the endpointing provider's | + +**These follow the assistant that carried them.** A tool on a saved assistant is org-configured and keeps your credentials. The same tool on a transient assistant or in `assistantOverrides` is caller-authored, and Vapi sends to its URL without them. + + +A saved assistant can carry a caller-authored subsystem server: if `assistantOverrides` replaces the voice, the tools, or the knowledge base, those replacements are caller-authored even though the assistant itself is saved. Give any subsystem server you supply in a request its own authentication in that block's `headers`. + + #### Confirming a withheld send in your logs When Vapi withholds credentials, it also writes an entry to the call's webhook logs: diff --git a/fern/squads/handoff/destinations.mdx b/fern/squads/handoff/destinations.mdx index 056b93522..bd8ba7711 100644 --- a/fern/squads/handoff/destinations.mdx +++ b/fern/squads/handoff/destinations.mdx @@ -149,6 +149,10 @@ Best for Anthropic models -- single tool with multiple destination options: The destination is determined at runtime via the `handoff-destination-request` webhook: + +A destination's `server` block follows the assistant carrying it. On a saved assistant it keeps your org's webhook credentials; supplied through a transient assistant or `assistantOverrides` it is caller-authored, and Vapi sends to it without them. Give it its own authentication in `server.headers`, as the examples below do. See [Server authentication](/server-url/server-authentication#subsystem-server-urls). + + ```json { "tools": [ @@ -217,7 +221,10 @@ Pass additional context to your webhook for intelligent routing: { "type": "dynamic", "server": { - "url": "https://api.example.com/intelligent-routing" + "url": "https://api.example.com/intelligent-routing", + "headers": { + "Authorization": "Bearer YOUR_API_KEY" + } } } ], From 11f7f9fe6814bbb0e2d943425c6b0da25afe286e Mon Sep 17 00:00:00 2001 From: Jeff Hoekman Date: Wed, 16 Sep 2026 15:42:06 -0400 Subject: [PATCH 2/2] VAP15-54 docs: drop the spaced hyphen in the subsystem intro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same ยง9 fix Steve applied across VAP15-53: a spaced hyphen standing in for a dash becomes a period, with the colon left to introduce the table. Also fixes the number disagreement the dash was hiding - "a tool, a knowledge base ... each carry" now reads as plurals throughout. Refs VAP15-54 Co-Authored-By: Claude Opus 5 --- fern/server-url/server-authentication.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fern/server-url/server-authentication.mdx b/fern/server-url/server-authentication.mdx index 5d8069b44..0309460f7 100644 --- a/fern/server-url/server-authentication.mdx +++ b/fern/server-url/server-authentication.mdx @@ -407,7 +407,7 @@ For webhooks sent to a server URL supplied in the API request, Vapi also strips #### Subsystem server URLs -Some webhooks go to a URL owned by a subsystem rather than to your assistant's webhook URL - a tool, a knowledge base, a custom voice, a dynamic handoff or transfer destination, or a custom endpointing provider each carry their own `server` block: +Some webhooks go to a URL owned by a subsystem rather than to your assistant's webhook URL. Tools, knowledge bases, custom voices, dynamic handoff and transfer destinations, and custom endpointing providers each carry their own `server` block: | Webhook | Server it is sent to | | --- | --- |