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:
Next.js
Express.js
Manual Verification
import { Inbound, verifyWebhookFromHeaders } from '@inboundemail/sdk'
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 })
}
How Verification Works
- Verification Token: Each endpoint has a unique verification token stored in its configuration
- Header Transmission: Inbound sends this token in the
X-Webhook-Verification-Token header with every webhook request
- SDK Verification: The
verifyWebhook function fetches your endpoint config via the API and compares tokens
- Security: If tokens don’t match, the request should be rejected
Always verify webhook requests in production to prevent unauthorized access to your endpoints.
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:
async function verifyWebhookManually(
endpointId: string,
verificationToken: string,
apiKey: string
): Promise<boolean> {
// Fetch endpoint from API
const response = await fetch(`https://inbound.new/api/v2/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:
import { Inbound } from '@inboundemail/sdk'
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
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:
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