diff --git a/fern/calls/assistant-based-warm-transfer.mdx b/fern/calls/assistant-based-warm-transfer.mdx index 1e7d3ce33..cbc8280ec 100644 --- a/fern/calls/assistant-based-warm-transfer.mdx +++ b/fern/calls/assistant-based-warm-transfer.mdx @@ -318,6 +318,6 @@ Configure your transfer assistant to: ## Next steps Now that you've configured assistant-based warm transfers: -- **[Call forwarding](mdc:docs/call-forwarding):** Learn about other transfer modes and options -- **[Assistant configuration](mdc:docs/assistants):** Configure assistant models and prompts -- **[Custom tools](mdc:docs/tools/custom-tools):** Add custom tools to your assistants +- **[Call forwarding](../call-forwarding):** Learn about other transfer modes and options +- **[Assistant configuration](../assistants):** Configure assistant models and prompts +- **[Custom tools](../tools/custom-tools):** Add custom tools to your assistants diff --git a/fern/customization/custom-transcriber.mdx b/fern/customization/custom-transcriber.mdx index 6157c8e82..741c6c511 100644 --- a/fern/customization/custom-transcriber.mdx +++ b/fern/customization/custom-transcriber.mdx @@ -408,9 +408,9 @@ You'll learn how to: "transcriber": { "provider": "custom-transcriber", "server": { - "url": "wss://your-server.ngrok.io/api/custom-transcriber" - }, - "secret": "your_optional_secret_value" + "url": "wss://your-server.ngrok.io/api/custom-transcriber", + "credentialId": "cred_transcriber_auth_123" + } }, "firstMessage": "Hello! I am using a custom transcriber with Deepgram." }, @@ -438,8 +438,8 @@ You'll learn how to: - **Streaming support requirement:** The custom transcriber must support streaming. Vapi sends continuous audio data over the WebSocket, and your server must handle this stream in real time. -- **Secret header:** - The custom transcriber configuration accepts an optional field called **`secret`**. When set, Vapi will send this value with every request as an HTTP header named `x-vapi-secret`. This can also be configured via a headers field. +- **Authentication:** + For secure transcriber endpoints, use **Custom Credentials** with `credentialId`. Create [Custom Credentials](../server-url/server-authentication) in the dashboard to manage Bearer Token, OAuth 2.0, or HMAC authentication. For backward compatibility, the legacy `secret` field is still supported and sends the value as an `x-vapi-secret` HTTP header. - **Buffering:** The solution buffers PCM audio and performs simple validation (e.g. ensuring stereo PCM data length is a multiple of 4). If the audio data is malformed, it is trimmed to a valid length. - **Channel detection:** diff --git a/fern/customization/custom-tts.mdx b/fern/customization/custom-tts.mdx index b12264f6c..d08d2e8e8 100644 --- a/fern/customization/custom-tts.mdx +++ b/fern/customization/custom-tts.mdx @@ -53,20 +53,20 @@ VAPI's custom TTS system operates through a webhook pattern: ## Authentication setup -VAPI needs secure communication with your TTS endpoint. Choose from these authentication options: +VAPI needs secure communication with your TTS endpoint. Use **Custom Credentials** for authentication: -### Secret header authentication +### Using Custom Credentials (Recommended) -The most common approach uses a secret token in the `X-VAPI-SECRET` header: +Create authentication credentials in the dashboard and reference them by ID: -```json title="Assistant Configuration" +```json title="Assistant Configuration with Custom Credentials" { "voice": { "provider": "custom-voice", "server": { "url": "https://your-tts-api.com/synthesize", - "secret": "your-secret-token-here", + "credentialId": "cred_tts_auth_123", "timeoutSeconds": 30 } } @@ -74,9 +74,13 @@ The most common approach uses a secret token in the `X-VAPI-SECRET` header: ``` -### Enhanced authentication with custom headers + +Create [Custom Credentials](../server-url/server-authentication) in the Vapi dashboard for better security and credential management. + + +### Legacy Authentication Methods -Add extra headers for API versioning or enhanced security: +For backward compatibility, you can still use inline authentication: ```json title="Assistant Configuration with Custom Headers" diff --git a/fern/server-url/server-authentication.mdx b/fern/server-url/server-authentication.mdx index 16aa9e994..03df2eb89 100644 --- a/fern/server-url/server-authentication.mdx +++ b/fern/server-url/server-authentication.mdx @@ -3,131 +3,553 @@ title: Server authentication slug: server-url/server-authentication --- -When configuring webhooks for your assistant, you can authenticate your server endpoints using either a secret token, custom headers, or OAuth2. This ensures that only authorized requests from Vapi are processed by your server. +When configuring webhooks for your assistant, you can authenticate your server endpoints by creating **Custom Credentials** and referencing them using a `credentialId`. This approach provides better security, reusability, and centralized management of your authentication credentials. -## Credential Configuration +## Overview -Credentials can be configured at multiple levels: +Vapi now uses a **credential-based authentication system** where you: -1. **Tool Call Level**: Create individual credentials for each tool call -2. **Assistant Level**: Set credentials directly in the assistant configuration -3. **Phone Number Level**: Configure credentials for specific phone numbers -4. **Organization Level**: Manage credentials in the [API Keys page](https://dashboard.vapi.ai/keys) +1. **Create Custom Credentials** through the dashboard +2. **Reference credentials by ID** in your server configurations +3. **Reuse credentials** across multiple assistants, phone numbers, and tools -The order of precedence is: -1. Tool call-level credentials -2. Assistant-level credentials -3. Phone number-level credentials -4. Organization-level credentials from the API Keys page +This replaces the previous inline authentication approach and provides better security and management capabilities. -## Authentication Methods +## Quick start -### Secret Token Authentication + + + In the Vapi dashboard, navigate to Custom Credentials and create a new credential: + + - Choose **Bearer Token** for simple API key authentication + - Enter a descriptive name like "Production API Auth" + - Add your API token + - Save the credential and note the generated ID (e.g., `cred_abc123`) + + + + Reference the credential when configuring server webhooks: + + ```json + { + "name": "Support Assistant", + "server": { + "url": "https://api.yourcompany.com/webhook", + "credentialId": "cred_abc123" + }, + "model": { + "provider": "openai", + "model": "gpt-4" + } + } + ``` + + + + Make a test call - Vapi will now authenticate requests to your webhook using the configured credential. + + + +## Creating Custom Credentials + +### Dashboard Management + +Custom Credentials are managed through the Vapi dashboard. Navigate to your organization settings to create and manage authentication credentials. + + + + + +You can create different types of authentication credentials: + +- **Bearer Token**: Simple token-based authentication +- **OAuth 2.0**: OAuth 2.0 client credentials flow +- **HMAC**: HMAC signature-based authentication + +## Authentication Types + +### Bearer Token Authentication + +The most common authentication method using a bearer token in the Authorization header. + + + + In the dashboard, select "Bearer Token" as the authentication type and configure: + + - **Credential Name**: A descriptive name for the credential + - **Token**: Your API token or secret + - **Header Name**: The header to send the token in (default: `Authorization`) + - **Include Bearer Prefix**: Whether to prefix the token with "Bearer " + + + + Reference the credential by its ID in your server configuration: + + ```json + { + "server": { + "url": "https://your-server.com/webhook", + "credentialId": "cred_abc123" + } + } + ``` + + + + + + + +#### Standard Authorization Header + +The most common Bearer Token configuration uses the standard `Authorization` header with the Bearer prefix: + + + + Configure a Bearer Token credential with: + + - **Header Name**: `Authorization` (default) + - **Include Bearer Prefix**: Enabled (toggle on) + - **Token**: Your API token or secret key + + + + Reference this credential in your server setup - Vapi will send your token as `Authorization: Bearer your-token`. + + ```json + { + "server": { + "url": "https://api.example.com/webhook", + "credentialId": "cred_bearer_standard_123" + } + } + ``` + + + + Your server will receive the standard Authorization header: + + ```http + POST /webhook HTTP/1.1 + Host: api.example.com + Authorization: Bearer your-api-token-here + Content-Type: application/json + ``` + + + +This is the recommended approach for modern API authentication and works with most authentication frameworks and libraries. + +#### Legacy X-Vapi-Secret Support + +For backward compatibility with existing implementations, you can configure a Bearer Token credential to use the `X-Vapi-Secret` header (matching the previous inline `secret` field behavior): + + + + Configure a Bearer Token credential with: + + - **Header Name**: `X-Vapi-Secret` (instead of `Authorization`) + - **Include Bearer Prefix**: Disabled (toggle off) + - **Token**: Your secret token value + + + + Reference this credential in your server setup - Vapi will send your token in the `X-Vapi-Secret` header exactly like the previous inline behavior. + + + + + + + +### OAuth 2.0 Authentication + +For OAuth 2.0 protected endpoints, configure client credentials flow with automatic token refresh. + + + + Select "OAuth 2.0" as the authentication type and configure: + + - **Credential Name**: A descriptive name for the credential + - **Token URL**: Your OAuth token endpoint + - **Client ID**: OAuth client identifier + - **Client Secret**: OAuth client secret + - **Scope**: Optional scopes to request + + + + Use the credential ID in your server setup: + + ```json + { + "server": { + "url": "https://your-server.com/webhook", + "credentialId": "cred_oauth_xyz789" + } + } + ``` + + + + + + + +#### OAuth 2.0 Flow + +1. Vapi makes a token request to your OAuth endpoint with client credentials +2. Your server validates the credentials and returns an access token +3. Vapi includes the access token in the Authorization header for webhook requests +4. When tokens expire, Vapi automatically requests new ones -The simplest way to authenticate webhook requests is using a secret token. Vapi will include this token in the `X-Vapi-Signature` header of each request. +#### Token Response Format -#### Configuration +Your OAuth server should return: ```json +{ + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "token_type": "Bearer", + "expires_in": 3600 +} +``` + +### HMAC Authentication + +For maximum security, use HMAC signature-based authentication to verify request integrity. + + + + Select "HMAC" as the authentication type and configure: + + - **Credential Name**: A descriptive name for the credential + - **Secret Key**: Your HMAC secret key + - **Algorithm**: Hash algorithm (SHA256, SHA1, etc.) + - **Signature Header**: Header name for the signature (e.g., `x-signature`) + - **Timestamp Header**: Optional timestamp header for replay protection + - **Payload Format**: How to format the payload for signing + + + + Reference the HMAC credential: + + ```json + { + "server": { + "url": "https://your-server.com/webhook", + "credentialId": "cred_hmac_456" + } + } + ``` + + + + + + + +## Using Credentials + +### In Assistant Configuration + +Reference credentials in your assistant's server configuration: + + +```json title="API Request" { "server": { - "url": "https://your-server.com/webhook", - "secret": "your-secret-token" + "url": "https://api.example.com/webhook", + "credentialId": "cred_bearer_auth_123" } } ``` -### Custom Headers Authentication +```typescript title="TypeScript SDK" +import { VapiClient } from "@vapi-ai/server-sdk"; -For more complex authentication scenarios, you can configure custom headers that Vapi will include with each webhook request. +const client = new VapiClient({ token: process.env.VAPI_API_KEY }); -This could include short lived JWTs/API Keys passed along via the Authorization header, or any other header that your server checks for. +const assistant = await client.assistants.create({ + server: { + url: "https://api.example.com/webhook", + credentialId: "cred_bearer_auth_123" + }, + // ... other assistant config +}); +``` -#### Configuration +```python title="Python SDK" +from vapi import Vapi -```json +client = Vapi(token=os.getenv("VAPI_API_KEY")) + +assistant = client.assistants.create( + server={ + "url": "https://api.example.com/webhook", + "credentialId": "cred_bearer_auth_123" + } + # ... other assistant config +) +``` + + + + + + +### In Phone Number Configuration + +Assign credentials to phone numbers for incoming call authentication: + + +```json title="API Request" { + "phoneNumber": "+1234567890", "server": { - "url": "https://your-server.com/webhook", - "headers": { - "Authorization": "Bearer your-api-key", - "Custom-Header": "custom-value" - } + "url": "https://api.example.com/calls", + "credentialId": "cred_oauth_456" } } ``` -### OAuth2 Authentication +```typescript title="TypeScript SDK" +const phoneNumber = await client.phoneNumbers.create({ + phoneNumber: "+1234567890", + server: { + url: "https://api.example.com/calls", + credentialId: "cred_oauth_456" + } +}); +``` + + + + + -For OAuth2-protected webhook endpoints, you can configure OAuth2 credentials that Vapi will use to obtain and refresh access tokens. +### In Tool Configuration -#### Configuration (at the assistant-level) +Secure your function tool endpoints with credentials: -```json + +```json title="API Request" { - "server": { - "url": "https://your-server.com/webhook" - }, - "credentials": [ - { - "provider": "webhook", - "authenticationPlan": { - "type": "oauth2", - "url": "https://your-server.com/oauth/token", - "clientId": "your-client-id", - "clientSecret": "your-client-secret", - "scope": "optional, only needed to specify which scopes to request access for" + "type": "function", + "function": { + "name": "get_weather", + "description": "Get current weather", + "parameters": { + "type": "object", + "properties": { + "location": { "type": "string" } } } - ] + }, + "server": { + "url": "https://api.example.com/weather", + "credentialId": "cred_hmac_789" + } } ``` -#### Configuration (via our Dashboard) +```typescript title="TypeScript SDK" +const tool = await client.tools.create({ + type: "function", + function: { + name: "get_weather", + description: "Get current weather", + parameters: { + type: "object", + properties: { + location: { type: "string" } + } + } + }, + server: { + url: "https://api.example.com/weather", + credentialId: "cred_hmac_789" + } +}); +``` + + +## Credential Management + +### Dashboard Features + +The Custom Credentials dashboard provides: + +- **Credential Creation**: Create new authentication credentials +- **Credential Editing**: Modify existing credential configurations +- **Credential Deletion**: Remove unused credentials +- **Usage Tracking**: See where credentials are being used + + + + + +### Best Practices + + +**Credential Naming**: Use descriptive names like "Production API Key" or "Staging OAuth" to easily identify credentials. + + + +**Credential Rotation**: Regularly rotate credentials for enhanced security. Update the credential in the dashboard without changing your configurations. + + + +**Credential Security**: Store credential secrets securely. Once created, secrets are encrypted and cannot be viewed in the dashboard. + + +### Migration from Inline Authentication + +If you're currently using inline authentication, migrate to the credential system: - - Go to [https://dashboard.vapi.ai/keys](https://dashboard.vapi.ai/keys) to manage your OAuth2 credentials. + + For each inline authentication configuration, create a matching Custom Credential in the dashboard: + + - **For `secret` field**: Create a Bearer Token credential with header `X-Vapi-Secret` and no Bearer prefix (see [Legacy X-Vapi-Secret Support](#legacy-x-vapi-secret-support)) + - **For `headers` field**: Create a Bearer Token credential with the appropriate header name + - **For OAuth configurations**: Create an OAuth 2.0 credential + + + + Replace inline authentication with `credentialId` references: + + **Before (inline secret):** + ```json + { + "server": { + "url": "https://api.example.com/webhook", + "secret": "your-secret-token" + } + } + ``` + + **After (credential reference):** + ```json + { + "server": { + "url": "https://api.example.com/webhook", + "credentialId": "cred_x_vapi_secret_123" + } + } + ``` + + Your server will continue receiving the same `X-Vapi-Secret` header with identical behavior. + + + + Verify that your webhooks continue working with the new credential system. The authentication behavior should be identical to your previous inline configuration. - - - +## Common Use Cases -#### OAuth2 Flow +### Single Credential for Multiple Resources -1. Vapi makes a request to your token endpoint with client credentials (Content-Type `application/x-www-form-urlencoded`) -2. Your server validates the credentials and returns an access token -3. Vapi includes the access token in the Authorization header for webhook requests -4. Your server validates the access token before processing the webhook -5. When the token expires, Vapi automatically requests a new one +Reuse the same credential across different components: + + +```json title="Shared Credential Usage" +{ + "assistant": { + "server": { + "url": "https://api.yourcompany.com/assistant-webhook", + "credentialId": "cred_production_api_123" + } + }, + "phoneNumber": { + "server": { + "url": "https://api.yourcompany.com/call-webhook", + "credentialId": "cred_production_api_123" + } + }, + "tools": [ + { + "type": "function", + "function": { + "name": "get_user_info" + }, + "server": { + "url": "https://api.yourcompany.com/user-info", + "credentialId": "cred_production_api_123" + } + } + ] +} +``` + -#### OAuth2 Token Response Format +### Environment-Specific Credentials -Your server should return a JSON response with the following format: +Use different credentials for staging and production: -```json + +```json title="Staging Environment" { - "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", - "token_type": "Bearer", - "expires_in": 3600 + "server": { + "url": "https://staging-api.yourcompany.com/webhook", + "credentialId": "cred_staging_api_456" + } } ``` -Example error response: +```json title="Production Environment" +{ + "server": { + "url": "https://api.yourcompany.com/webhook", + "credentialId": "cred_production_api_123" + } +} +``` + -```json +### Service-Specific Credentials + +Use different credentials for different services: + + +```json title="Multiple Service Credentials" { - "error": "invalid_client", - "error_description": "Invalid client credentials" + "assistant": { + "server": { + "url": "https://auth.yourcompany.com/webhook", + "credentialId": "cred_auth_service_789" + } + }, + "tools": [ + { + "type": "function", + "function": { + "name": "payment_processing" + }, + "server": { + "url": "https://payments.yourcompany.com/process", + "credentialId": "cred_payment_service_321" + } + }, + { + "type": "function", + "function": { + "name": "user_management" + }, + "server": { + "url": "https://users.yourcompany.com/manage", + "credentialId": "cred_user_service_654" + } + } + ] } ``` + + +## Next steps -Common error types: -- `invalid_client`: Invalid client credentials -- `invalid_grant`: Invalid or expired refresh token -- `invalid_scope`: Invalid scope requested -- `unauthorized_client`: Client not authorized for this grant type +Now that you have authentication configured: - If using the OAuth2 flow for authenticating tool calls, make sure the server for the tool is the URL that should be hit *after* we have completed the token exchange. \ No newline at end of file +- **[Setting server URLs](./setting-server-urls):** Learn where server URLs can be configured +- **[Server events](./events):** Understand what webhook events Vapi sends +- **[Local development](./developing-locally):** Set up local webhook testing \ No newline at end of file diff --git a/fern/server-url/setting-server-urls.mdx b/fern/server-url/setting-server-urls.mdx index d450d062b..80f96b08c 100644 --- a/fern/server-url/setting-server-urls.mdx +++ b/fern/server-url/setting-server-urls.mdx @@ -43,7 +43,13 @@ Here's a breakdown of where you can set server URLs in Vapi: - **At Import:** when you [import from Twilio](/api-reference/phone-numbers/import-twilio-number) or [Vonage](/api-reference/phone-numbers/import-vonage-number) - **Via Update:** you can [update a number](/api-reference/phone-numbers/update-phone-number) already in your account - The field `phoneNumber.serverUrl` will contain the server URL for the phone number. + The phone number's server configuration includes both the URL and optional authentication: + - `phoneNumber.server.url`: The webhook endpoint URL + - `phoneNumber.server.credentialId`: Authentication credential ID (optional) + + + For secured webhooks, create [Custom Credentials](./server-authentication) and reference them using `credentialId`. + @@ -60,9 +66,15 @@ Here's a breakdown of where you can set server URLs in Vapi: - At [assistant creation](/api-reference/assistants/create-assistant) (or via an [update](/api-reference/assistants/update-assistant)) you can set the assistant's server URL. - - The server URL for an assistant is stored in the `assistant.serverUrl` field. + At [assistant creation](/api-reference/assistants/create-assistant) (or via an [update](/api-reference/assistants/update-assistant)) you can set the assistant's server configuration. + + The assistant's server configuration includes: + - `assistant.server.url`: The webhook endpoint URL + - `assistant.server.credentialId`: Authentication credential ID (optional) + + + For secured webhooks, use [Custom Credentials](./server-authentication) with `credentialId` instead of inline authentication. + @@ -79,9 +91,17 @@ Here's a breakdown of where you can set server URLs in Vapi: - The server URL for a function call can be found on an assistant at `assistant.model.functions[].serverUrl`. + Function tools can be configured with server endpoints via the [tools API](/api-reference/tools) or within assistant configurations. + + The server configuration for function tools includes: + - `tool.server.url`: The function endpoint URL + - `tool.server.credentialId`: Authentication credential ID (optional) - You can either set the URL for a function call at [assistant creation](/api-reference/assistants/create-assistant), or in an [assistant update](/api-reference/assistants/update-assistant). + You can configure function tool servers at [tool creation](/api-reference/tools/create), [assistant creation](/api-reference/assistants/create-assistant), or in updates. + + + Use [Custom Credentials](./server-authentication) to secure your function endpoints with `credentialId`. + diff --git a/fern/static/images/server-url/authentication/bearer-token-credential.png b/fern/static/images/server-url/authentication/bearer-token-credential.png new file mode 100644 index 000000000..3cbcc39fa Binary files /dev/null and b/fern/static/images/server-url/authentication/bearer-token-credential.png differ diff --git a/fern/static/images/server-url/authentication/credential-selection-assistant-server.png b/fern/static/images/server-url/authentication/credential-selection-assistant-server.png new file mode 100644 index 000000000..8136878d9 Binary files /dev/null and b/fern/static/images/server-url/authentication/credential-selection-assistant-server.png differ diff --git a/fern/static/images/server-url/authentication/credential-selection-phone-number-server.png b/fern/static/images/server-url/authentication/credential-selection-phone-number-server.png new file mode 100644 index 000000000..b6e2f3a40 Binary files /dev/null and b/fern/static/images/server-url/authentication/credential-selection-phone-number-server.png differ diff --git a/fern/static/images/server-url/authentication/credential-selection.png b/fern/static/images/server-url/authentication/credential-selection.png new file mode 100644 index 000000000..f146b2da1 Binary files /dev/null and b/fern/static/images/server-url/authentication/credential-selection.png differ diff --git a/fern/static/images/server-url/authentication/custom-credentials-dashboard.png b/fern/static/images/server-url/authentication/custom-credentials-dashboard.png new file mode 100644 index 000000000..df6e1d532 Binary files /dev/null and b/fern/static/images/server-url/authentication/custom-credentials-dashboard.png differ diff --git a/fern/static/images/server-url/authentication/hmac-credential.png b/fern/static/images/server-url/authentication/hmac-credential.png new file mode 100644 index 000000000..7baf82e1e Binary files /dev/null and b/fern/static/images/server-url/authentication/hmac-credential.png differ diff --git a/fern/static/images/server-url/authentication/oauth2-credential.png b/fern/static/images/server-url/authentication/oauth2-credential.png new file mode 100644 index 000000000..419ab0860 Binary files /dev/null and b/fern/static/images/server-url/authentication/oauth2-credential.png differ diff --git a/fern/static/images/server-url/authentication/x-vapi-secret-credential.png b/fern/static/images/server-url/authentication/x-vapi-secret-credential.png new file mode 100644 index 000000000..3d754d39a Binary files /dev/null and b/fern/static/images/server-url/authentication/x-vapi-secret-credential.png differ