> ## Documentation Index
> Fetch the complete documentation index at: https://inbound.new/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Security

> How to securely verify webhook requests from Inbound

## Overview

When receiving webhooks from Inbound, it's important to verify that requests are legitimate. Inbound includes a verification token in the `X-Webhook-Verification-Token` header for each webhook request.

## Webhook Verification

Every webhook request includes security headers that allow you to verify the request authenticity:

| Header | Description |
| - | - |
| `X-Webhook-Verification-Token` | Unique verification token for your endpoint |
| `X-Endpoint-ID` | ID of the endpoint that triggered this webhook |
| `X-Webhook-Event` | Event type (e.g., `email.received`) |
| `X-Webhook-Timestamp` | ISO 8601 timestamp of when the webhook was sent |

## Using the SDK Verification Helper

The SDK provides a `verifyWebhook` helper function that automatically fetches your endpoint configuration and compares the verification token:

> [tab] Next.js
>
> ```typescript app/api/webhook/route.ts theme={null}
> import { Inbound, verifyWebhookFromHeaders } from 'inboundemail'
>
> const inbound = new Inbound(process.env.INBOUND_API_KEY!)
>
> export async function POST(request: Request) {
>   // Verify webhook authenticity
>   const isValid = await verifyWebhookFromHeaders(request.headers, inbound)
>
>   if (!isValid) {
>     return new Response('Unauthorized', { status: 401 })
>   }
>
>   // Process webhook payload
>   const payload = await request.json()
>   const email = payload.email
>
>   // Your webhook handling logic here
>   console.log('Received email:', email.subject)
>
>   return new Response('OK', { status: 200 })
> }
> ```

> [tab] Express.js
>
> ```typescript server.ts theme={null}
> import express from 'express'
> import { Inbound, verifyWebhookFromHeaders } from 'inboundemail'
>
> const app = express()
> const inbound = new Inbound(process.env.INBOUND_API_KEY!)
>
> app.post('/webhook', async (req, res) => {
>   // Verify webhook authenticity
>   const isValid = await verifyWebhookFromHeaders(req.headers, inbound)
>
>   if (!isValid) {
>     return res.status(401).json({ error: 'Unauthorized' })
>   }
>
>   // Process webhook payload
>   const email = req.body.email
>
>   // Your webhook handling logic here
>   console.log('Received email:', email.subject)
>
>   res.status(200).json({ success: true })
> })
> ```

> [tab] Manual Verification
>
> ```typescript theme={null}
> import { Inbound, verifyWebhook } from 'inboundemail'
>
> const inbound = new Inbound(process.env.INBOUND_API_KEY!)
>
> export async function POST(request: Request) {
>   const endpointId = request.headers.get('X-Endpoint-ID')
>   const verificationToken = request.headers.get('X-Webhook-Verification-Token')
>
>   // Manually verify with extracted headers
>   const isValid = await verifyWebhook(endpointId, verificationToken, inbound)
>
>   if (!isValid) {
>     return new Response('Unauthorized', { status: 401 })
>   }
>
>   // Process webhook...
> }
> ```

## How Verification Works

1. **Verification Token**: Each endpoint has a unique verification token stored in its configuration
2. **Header Transmission**: Inbound sends this token in the `X-Webhook-Verification-Token` header with every webhook request
3. **SDK Verification**: The `verifyWebhook` function fetches your endpoint config via the API and compares tokens
4. **Security**: If tokens don't match, the request should be rejected

> [!WARNING]
>
> Always verify webhook requests in production to prevent unauthorized access to your endpoints.

> [!TIP]
>
> The verification token is automatically generated when you create an endpoint. You can view it in your endpoint configuration via the API.

## Manual Verification (Without SDK)

If you're not using the SDK, you can manually verify webhooks by fetching the endpoint configuration:

```typescript theme={null}
async function verifyWebhookManually(
  endpointId: string,
  verificationToken: string,
  apiKey: string
): Promise<boolean> {
  // Fetch endpoint from API
  const response = await fetch(`https://inbound.new/api/e2/endpoints/${endpointId}`, {
    headers: {
      'Authorization': `Bearer ${apiKey}`
    }
  })
  
  if (!response.ok) {
    return false
  }
  
  const endpoint = await response.json()
  const config = typeof endpoint.config === 'string' 
    ? JSON.parse(endpoint.config) 
    : endpoint.config
  
  // Compare tokens
  return config.verificationToken === verificationToken
}
```

## Getting Your Verification Token

You can retrieve the verification token for your endpoint via the API:

```typescript theme={null}
import { Inbound } from 'inboundemail'

const inbound = new Inbound(process.env.INBOUND_API_KEY!)

// Get endpoint configuration
const { data: endpoint } = await inbound.endpoint.get('your-endpoint-id')

if (endpoint) {
  const config = typeof endpoint.config === 'string' 
    ? JSON.parse(endpoint.config) 
    : endpoint.config
  
  console.log('Verification token:', config.verificationToken)
}
```

## Best Practices

### Always Verify in Production

> [!WARNING]
>
> Never skip webhook verification in production environments. Unverified webhooks can expose your application to security risks.

### Handle Verification Failures

Always return appropriate error responses when verification fails:

```typescript theme={null}
if (!isValid) {
  // Log the failed attempt for monitoring
  console.warn('Webhook verification failed', {
    endpointId: request.headers.get('X-Endpoint-ID'),
    timestamp: new Date().toISOString()
  })
  
  // Return 401 Unauthorized
  return new Response('Unauthorized', { status: 401 })
}
```

### Store API Keys Securely

Never hardcode API keys or commit them to version control:

* Use environment variables
* Use secrets management services in production
* Rotate API keys regularly

## Next Steps

> [card] [Webhook Structure](https://inbound.new/docs/api-reference/webhook.md)
>
> Learn about webhook payload structure and types

> [card] [API Reference](https://inbound.new/docs/api-reference/endpoints/get-endpoint-details.md)
>
> View endpoint API documentation

> [card] [Error Codes](https://inbound.new/docs/api-reference/errors.md)
>
> Understand authentication and verification errors

> [card] [SDK Documentation](https://inbound.new/docs/api-reference/webhook.md#verifying-webhooks-with-the-sdk)
>
> Learn more about webhook handling in the SDK


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.