Events API
Track user interactions and 404 errors for analytics. The Events API is designed for server-side integration, allowing you to forward events from your application server to deadend.ai.
Overview
The Events API (POST /v1/events) is an authenticated endpoint designed for server-side integration. Your application server receives events from browsers and forwards them to our API using your project's API key.
Architecture:
Browser → Your Application Server → Customer APIKey Features:
- ✅ API Key Authentication Required - Ensures events are tied to authenticated projects
- ✅ Automatic Project ID Extraction - Project ID is extracted from the API key, no need to include it in requests
- ✅ Asynchronous Processing - Returns immediately (204 No Content) without blocking
- ✅ Automatic Event Type Detection - Single endpoint handles multiple event types
- ✅ Rate Limiting - Rate limits are enforced based on your subscription plan
- ✅ Secure - API keys never exposed to browsers
Authentication
API key authentication is required for the Events API. Your application server should include your API key in the Authorization header:
Authorization: Bearer your_api_key_hereImportant: Never expose your API key to browsers. The API key should only be used on your application server.
The project_id is automatically extracted from your API key and does not need to be included in the request body. This ensures events are always tied to the correct project.
Endpoint
Base URL: POST /v1/events
Content-Type: application/json
Response: 204 No Content (on success)
Event Types
The endpoint automatically detects the event type based on the request payload:
- Click Events - User clicks on search suggestions
- 404 Events - Page not found errors
Event Type Detection
- Click Event: Request contains
clicked_urlandsearch_idfields - 404 Event: Request contains
raw_pathbut noclicked_urlorsearch_idfields
Click Events
Track when users click on search suggestions.
Request Payload
{
"clicked_url": "/products/blue-widget-v2",
"clicked_rank": 1,
"raw_path": "/prodcts/blue-widjet",
"search_id": "a1b2c3d4-e5f6-a7b8-c9d0-e1f2a3b4c5d6",
"origin": "https://example.com",
"timestamp": "2025-11-04T12:34:56Z"
}Note: project_id is not included in the request - it is automatically extracted from your API key.
Required Fields
| Field | Type | Description |
|---|---|---|
clicked_url | string | The URL that was clicked |
clicked_rank | number | The rank/position of the clicked suggestion (1-indexed) |
raw_path | string | The original search path/query |
search_id | string | The search ID from the search API response |
Optional Fields
| Field | Type | Description |
|---|---|---|
origin | string | Website domain (e.g., "https://example.com (opens in a new tab)") |
timestamp | string | ISO 8601 timestamp (auto-generated if not provided) |
Example Request
curl -X POST https://api.deadend.ai/v1/events \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"clicked_url": "/products/blue-widget-v2",
"clicked_rank": 1,
"raw_path": "/prodcts/blue-widjet",
"search_id": "a1b2c3d4-e5f6-a7b8-c9d0-e1f2a3b4c5d6",
"origin": "https://example.com"
}'404 Events
Track when users encounter page not found errors.
Request Payload
{
"raw_path": "/prodcts/blue-widjet",
"origin": "https://example.com",
"referrer": "https://example.com/search",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...",
"user_ip": "89.102.103.104"
}Note: project_id is not included in the request - it is automatically extracted from your API key.
Required Fields
| Field | Type | Description |
|---|---|---|
raw_path | string | The path that resulted in a 404 error |
Optional Fields
| Field | Type | Description |
|---|---|---|
origin | string | Website domain (e.g., "https://example.com (opens in a new tab)") |
referrer | string | The referring page URL |
user_agent | string | Browser user agent |
user_ip | string | User's IP address |
Example Request
curl -X POST https://api.deadend.ai/v1/events \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"raw_path": "/prodcts/blue-widjet",
"origin": "https://example.com",
"referrer": "https://example.com/search"
}'Response Format
Success Response
Status Code: 204 No Content
Body: Empty
The endpoint returns immediately after validation, allowing the browser to continue without waiting for event processing.
Error Responses
400 Bad Request
{
"error": {
"code": "invalid_request",
"message": "Missing required parameter: clicked_url",
"param": "clicked_url"
}
}Common error scenarios:
- Missing required fields
- Invalid JSON payload
- Unable to determine event type
401 Unauthorized
{
"error": {
"code": "invalid_api_key",
"message": "Authorization header is required"
}
}Occurs when:
- Missing
Authorizationheader - Invalid API key
- API key not found
403 Forbidden
{
"error": {
"code": "insufficient_permissions",
"message": "API access not available for this project"
}
}Occurs when:
- Rate limit exceeded
- Rate limit exceeded
405 Method Not Allowed
{
"error": {
"code": "method_not_allowed",
"message": "Only POST method is allowed"
}
}Integration Architecture
The Events API follows a server-to-server architecture:
┌─────────┐ ┌──────────────────┐ ┌──────────────┐
│ Browser │ ──────> │ Your App Server │ ──────> │ Customer API │
└─────────┘ └──────────────────┘ └──────────────┘- Browser sends events to your application server (no API key needed)
- Your Application Server forwards events to Customer API (with API key)
- Customer API processes events asynchronously
Best Practices
-
Never Expose API Keys: API keys should only be used on your application server, never in browser/client-side code
-
Server-Side Proxy: Always proxy events through your application server to keep API keys secure
-
Don't Block User Experience: The endpoint returns immediately, so don't wait for the response before continuing user navigation
-
Handle Errors Gracefully: Use
.catch()or try-catch to handle network errors silently on both browser and server -
Respect User Privacy: Only send necessary data. User IP and user agent are optional
-
Use Origin Field: Always include the
originfield to help identify which website the event came from -
Rate Limiting: Be aware of your plan's rate limits. Events are subject to the same rate limits as other API endpoints
-
Environment Variables: Store API keys in environment variables on your server, never in code repositories
Error Handling
The Events API is designed to be resilient:
- Network Failures: Events are sent asynchronously, so network failures won't block your application
- Invalid Events: Invalid events return
400 Bad Requestbut don't crash the service
Always handle errors gracefully in your application. The endpoint returns 204 No Content on success, so you can proceed without waiting for a response. If you receive an error response, log it for debugging but don't interrupt the user experience.
Rate Limiting
The Events API enforces rate limiting based on your subscription plan using a Token Bucket algorithm. As a read endpoint, it follows the same limits as other read endpoints (/v1/suggest, /v1/semantic-search, /v1/retrieve):
| Plan | Sustained Limit | Burst Limit |
|---|---|---|
| Hacker (Free) | 2 req/sec | 5 req/sec |
| Solo ($9/mo) | 10 req/sec | 20 req/sec |
| Startup ($29/mo) | 25 req/sec | 50 req/sec |
| Scale ($99/mo) | 50 req/sec | 100 req/sec |
How Token Bucket Works: The sustained limit is your average rate over time. The burst limit allows you to exceed the sustained rate for short periods (e.g., during traffic spikes). If you sustain requests above the sustained limit, you'll be throttled back down.
Rate limit information is included in response headers:
X-RateLimit-Limit: Maximum requests allowedX-RateLimit-Remaining: Remaining requests in current windowX-RateLimit-Reset: Unix timestamp when the limit resets
When rate limits are exceeded, you'll receive a 429 Too Many Requests response.
Next Steps
- Authentication - Learn about API keys
- Search API - Understand the search endpoints that generate search IDs
- Error Handling - Handle errors gracefully