Destinations API
Destinations are delivery targets for webhooks. Hookbase supports HTTP endpoints and warehouse destinations (S3, R2, GCS, Azure Blob).
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/destinations | List destinations |
| POST | /api/destinations | Create destination |
| GET | /api/destinations/{id} | Get destination |
| PATCH | /api/destinations/{id} | Update destination |
| DELETE | /api/destinations/{id} | Delete destination |
| POST | /api/destinations/{id}/test | Test destination |
| GET | /api/destinations/export | Export destinations as JSON |
| POST | /api/destinations/import | Import destinations from JSON |
| DELETE | /api/destinations/bulk | Bulk delete destinations |
Destination Object
HTTP Destination
{
"id": "dst_xyz789",
"name": "Production API",
"type": "http",
"url": "https://api.yourapp.com/webhooks",
"method": "POST",
"headers": {
"X-Custom-Header": "value"
},
"authType": "bearer",
"authConfig": {
"token": "sk_live_xxx"
},
"timeoutMs": 30000,
"rateLimitPerMinute": 500,
"retryPolicy": {
"maxRetries": 5,
"initialDelay": 1000,
"maxDelay": 60000,
"backoffMultiplier": 2
},
"enabled": true,
"successRate": 98.5,
"avgLatency": 245,
"deliveriesCount": 5230,
"lastDeliveryAt": "2024-01-15T10:30:00Z",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}Warehouse Destination (S3 example)
{
"id": "dst_wh_abc123",
"name": "Analytics Data Lake",
"type": "s3",
"url": "",
"config": {
"bucket": "my-data-lake",
"region": "us-east-1",
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "••••EKEY"
},
"fieldMapping": [
{ "source": "$.payload.type", "target": "event_type", "type": "string" },
{ "source": "$.payload.data.amount", "target": "amount", "type": "number" }
],
"enabled": true,
"createdAt": "2026-02-21T10:30:00Z",
"updatedAt": "2026-02-21T10:30:00Z"
}Info
Credential Redaction
Sensitive fields (secretAccessKey, serviceAccountKey, accountKey) are returned as •••• followed by the last 4 characters. Credentials are encrypted at rest using AES-256-GCM.
List Destinations
GET /api/destinationsQuery Parameters
| Parameter | Type | Description |
|---|---|---|
| page | number | Page number (default: 1) |
| pageSize | number | Items per page (default: 20, max: 100) |
| enabled | boolean | Filter by enabled status |
| search | string | Search by name or URL |
Example
curl https://api.hookbase.app/api/destinations \
-H "Authorization: Bearer whr_your_api_key"Response
{
"data": [
{
"id": "dst_xyz789",
"name": "Production API",
"type": "http",
"url": "https://api.yourapp.com/webhooks",
"enabled": true,
"successRate": 98.5,
"avgLatency": 245,
"deliveriesCount": 5230
},
{
"id": "dst_wh_abc123",
"name": "Analytics Data Lake",
"type": "s3",
"url": "",
"config": {
"bucket": "my-data-lake",
"region": "us-east-1",
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "••••EKEY"
},
"enabled": true
}
],
"pagination": {
"total": 5,
"page": 1,
"pageSize": 20
}
}Create Destination
POST /api/destinationsCommon Fields
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Display name |
| type | string | No | http (default), s3, r2, gcs, or azure_blob |
| enabled | boolean | No | Active status (default: true) |
HTTP-Specific Fields
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | Delivery URL (HTTPS recommended) |
| method | string | No | HTTP method: POST, PUT, PATCH (default: POST) |
| headers | object | No | Custom headers to include |
| authType | string | No | Authentication type (see below) |
| authConfig | object | No | Authentication configuration |
| timeoutMs | number | No | Request timeout in milliseconds (default: 30000, max: 60000) |
| rateLimitPerMinute | number | No | Max deliveries per minute (null = unlimited) |
| retryPolicy | object | No | Retry configuration |
Warehouse-Specific Fields
| Field | Type | Required | Description |
|---|---|---|---|
| config | object | Yes | Provider-specific configuration (see below) |
| fieldMapping | array | No | Field mapping rules for structured output |
Tip
Plan Requirement
Warehouse destinations (s3, r2, gcs, azure_blob) require a Pro or Business plan.
Authentication Types (HTTP)
| Type | Description | Auth Config |
|---|---|---|
none | No authentication | -- |
basic | HTTP Basic Auth | { "username": "...", "password": "..." } |
bearer | Bearer token | { "token": "..." } |
api_key | API key in header | { "headerName": "X-API-Key", "key": "..." } |
custom_header | Custom auth header | { "headerName": "...", "headerValue": "..." } |
Warehouse Config: S3
{
"bucket": "my-data-lake",
"region": "us-east-1",
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"prefix": "webhooks/",
"fileFormat": "jsonl",
"partitionBy": "date"
}| Field | Type | Required | Description |
|---|---|---|---|
| bucket | string | Yes | S3 bucket name (3-63 chars) |
| region | string | Yes | AWS region |
| accessKeyId | string | Yes | AWS access key ID |
| secretAccessKey | string | Yes | AWS secret access key |
| prefix | string | No | Path prefix |
| fileFormat | string | No | jsonl (default) or json |
| partitionBy | string | No | date (default), hour, or source |
Warehouse Config: R2
{
"bucket": "my-webhook-archive",
"endpoint": "https://ACCOUNT_ID.r2.cloudflarestorage.com",
"accessKeyId": "your-r2-access-key-id",
"secretAccessKey": "your-r2-secret-access-key",
"prefix": "webhooks/",
"fileFormat": "jsonl",
"partitionBy": "date"
}| Field | Type | Required | Description |
|---|---|---|---|
| bucket | string | Yes | R2 bucket name (3-63 chars) |
| endpoint | string | Yes | R2 S3-compatible API endpoint (https://{account_id}.r2.cloudflarestorage.com) |
| accessKeyId | string | Yes | R2 API token access key ID |
| secretAccessKey | string | Yes | R2 API token secret access key (encrypted at rest) |
| prefix | string | No | Path prefix |
| fileFormat | string | No | jsonl (default) or json |
| partitionBy | string | No | date (default), hour, or source |
Warehouse Config: GCS
{
"bucket": "my-gcs-bucket",
"projectId": "my-gcp-project",
"serviceAccountKey": "{...}",
"prefix": "webhooks/",
"fileFormat": "jsonl",
"partitionBy": "date"
}| Field | Type | Required | Description |
|---|---|---|---|
| bucket | string | Yes | GCS bucket name (3-63 chars) |
| projectId | string | Yes | Google Cloud project ID |
| serviceAccountKey | string | Yes | Service account key JSON |
| prefix | string | No | Path prefix |
| fileFormat | string | No | jsonl (default) or json |
| partitionBy | string | No | date (default), hour, or source |
Warehouse Config: Azure Blob
{
"accountName": "myaccount",
"accountKey": "base64-encoded-key",
"containerName": "webhook-data",
"prefix": "webhooks/",
"fileFormat": "jsonl",
"partitionBy": "date"
}| Field | Type | Required | Description |
|---|---|---|---|
| accountName | string | Yes | Storage account name (3-24 chars) |
| accountKey | string | Yes | Base64-encoded account key |
| containerName | string | Yes | Blob container name (3-63 chars) |
| prefix | string | No | Path prefix |
| fileFormat | string | No | jsonl (default) or json |
| partitionBy | string | No | date (default), hour, or source |
Field Mapping
| Field | Type | Required | Description |
|---|---|---|---|
| source | string | Yes | JSONPath expression (e.g., $.payload.amount) |
| target | string | Yes | Output column name |
| type | string | Yes | string, number, boolean, timestamp, or json |
| default | string | No | Default value if source path is missing |
Maximum 50 field mappings per destination.
Example: Create HTTP Destination
curl -X POST https://api.hookbase.app/api/destinations \
-H "Authorization: Bearer whr_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Production API",
"type": "http",
"url": "https://api.yourapp.com/webhooks/handler",
"headers": {
"Authorization": "Bearer sk_live_xxx"
},
"retryPolicy": {
"maxRetries": 5,
"initialDelay": 1000,
"maxDelay": 300000
}
}'Example: Create S3 Warehouse Destination
curl -X POST https://api.hookbase.app/api/destinations \
-H "Authorization: Bearer whr_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Analytics Data Lake",
"type": "s3",
"config": {
"bucket": "my-data-lake",
"region": "us-east-1",
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"prefix": "webhooks/stripe/",
"fileFormat": "jsonl",
"partitionBy": "date"
},
"fieldMapping": [
{ "source": "$.payload.type", "target": "event_type", "type": "string" },
{ "source": "$.payload.data.amount", "target": "amount", "type": "number" },
{ "source": "$.payload.created", "target": "created_at", "type": "timestamp" }
]
}'Response
{
"id": "dst_wh_new456",
"name": "Analytics Data Lake",
"type": "s3",
"config": {
"bucket": "my-data-lake",
"region": "us-east-1",
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "••••EKEY"
},
"fieldMapping": [
{ "source": "$.payload.type", "target": "event_type", "type": "string" },
{ "source": "$.payload.data.amount", "target": "amount", "type": "number" },
{ "source": "$.payload.created", "target": "created_at", "type": "timestamp" }
],
"enabled": true,
"createdAt": "2026-02-21T10:30:00Z",
"updatedAt": "2026-02-21T10:30:00Z"
}Get Destination
GET /api/destinations/{id}Example
curl https://api.hookbase.app/api/destinations/dst_xyz789 \
-H "Authorization: Bearer whr_your_api_key"Response
Returns the full destination object. Sensitive credential fields are redacted.
Update Destination
PATCH /api/destinations/{id}Request Body
All fields are optional. Only provided fields are updated.
| Field | Type | Description |
|---|---|---|
| name | string | Display name |
| url | string | Delivery URL (HTTP destinations) |
| headers | object | Custom headers (replaces existing) |
| retryPolicy | object | Retry configuration |
| config | object | Warehouse configuration |
| fieldMapping | array | Field mapping rules |
| enabled | boolean | Active status |
Info
Updating Credentials
When updating a warehouse destination, redacted credential values (e.g., ••••EKEY) are automatically preserved. Only provide a new value if you are rotating keys.
Example
curl -X PATCH https://api.hookbase.app/api/destinations/dst_xyz789 \
-H "Authorization: Bearer whr_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.yourapp.com/webhooks/v2/handler",
"retryPolicy": {
"maxRetries": 10
}
}'Response
Returns the updated destination object.
Delete Destination
DELETE /api/destinations/{id}Warning
Deleting a destination removes it from all routes. Deliveries are preserved for history.
Example
curl -X DELETE https://api.hookbase.app/api/destinations/dst_xyz789 \
-H "Authorization: Bearer whr_your_api_key"Response
204 No ContentTest Destination
Send a test webhook (HTTP) or upload a test file (warehouse) to verify the destination is configured correctly.
POST /api/destinations/{id}/testRequest Body (Optional)
| Field | Type | Description |
|---|---|---|
| payload | object | Custom test payload (default: sample webhook event) |
Example
curl -X POST https://api.hookbase.app/api/destinations/dst_xyz789/test \
-H "Authorization: Bearer whr_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"payload": {
"event": "test",
"timestamp": "2024-01-15T10:30:00Z"
}
}'HTTP Destination Response
{
"success": true,
"statusCode": 200,
"latency": 245,
"responseBody": "{\"received\": true}",
"message": "Test webhook delivered successfully"
}Warehouse Destination Response
{
"success": true,
"result": {
"key": "hookbase/2026-02-21/test-1740150000000.jsonl",
"size": 142,
"count": 1
},
"message": "Test file uploaded successfully"
}Error Response
{
"success": false,
"statusCode": 503,
"latency": 30012,
"error": "Connection timeout after 30000ms",
"message": "Test webhook delivery failed"
}Destination Health
Get health metrics for a destination:
GET /api/destinations/{id}/healthResponse
{
"successRate": 98.5,
"avgLatency": 245,
"p50Latency": 180,
"p95Latency": 450,
"p99Latency": 890,
"totalDeliveries": 5230,
"successfulDeliveries": 5152,
"failedDeliveries": 78,
"lastDeliveryAt": "2024-01-15T10:30:00Z",
"lastSuccessAt": "2024-01-15T10:30:00Z",
"lastFailureAt": "2024-01-15T09:15:00Z",
"status": "healthy"
}Status Values
| Status | Description |
|---|---|
healthy | Success rate > 95% |
degraded | Success rate 80-95% |
failing | Success rate < 80% |
unknown | No recent deliveries |
Export Destinations
Export destinations as a JSON file for backup or migration to another organization.
GET /api/destinations/exportQuery Parameters
| Parameter | Type | Description |
|---|---|---|
| ids | string | Comma-separated destination IDs to export (optional, exports all if not specified) |
| includeSensitive | boolean | Include auth credentials in export (default: false) |
Example
# Export all destinations (auth credentials redacted)
curl https://api.hookbase.app/api/destinations/export \
-H "Authorization: Bearer whr_your_api_key"
# Export specific destinations with credentials
curl "https://api.hookbase.app/api/destinations/export?ids=dst_1,dst_2&includeSensitive=true" \
-H "Authorization: Bearer whr_your_api_key"Response
{
"version": "1.0",
"exportedAt": "2024-01-15T10:30:00Z",
"organizationSlug": "myorg",
"destinations": [
{
"name": "Production API",
"slug": "production-api",
"type": "http",
"url": "https://api.yourapp.com/webhooks",
"method": "POST",
"headers": {
"X-Custom-Header": "value"
},
"authType": "bearer",
"authConfig": "***REDACTED***",
"timeoutMs": 30000,
"rateLimitPerMinute": null,
"isActive": true
}
]
}Tip
When includeSensitive is false (default), authentication credentials are replaced with ***REDACTED***. You'll need to reconfigure auth settings after importing.
Import Destinations
Import destinations from a JSON export file.
POST /api/destinations/importRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
| destinations | array | Yes | Array of destination objects to import |
| conflictStrategy | string | Yes | How to handle slug conflicts: skip, rename, or overwrite |
| validateOnly | boolean | No | If true, validates without importing (default: false) |
Conflict Strategies
| Strategy | Description |
|---|---|
skip | Skip destinations that already exist (by slug) |
rename | Auto-rename conflicting destinations (e.g., api -> api-1) |
overwrite | Update existing destinations with imported data |
Example
curl -X POST https://api.hookbase.app/api/destinations/import \
-H "Authorization: Bearer whr_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"destinations": [
{
"name": "Staging API",
"slug": "staging-api",
"type": "http",
"url": "https://staging.yourapp.com/webhooks",
"method": "POST",
"timeoutMs": 30000,
"isActive": true
}
],
"conflictStrategy": "skip"
}'Response
{
"success": true,
"summary": {
"imported": 3,
"skipped": 1,
"overwritten": 0,
"failed": 0
},
"details": {
"imported": ["Staging API", "Development API", "QA Endpoint"],
"skipped": ["Production API"],
"overwritten": [],
"failed": []
}
}Bulk Delete Destinations
Delete multiple destinations in a single request.
DELETE /api/destinations/bulkRequest Body
{
"ids": ["dst_abc123", "dst_def456", "dst_ghi789"]
}Example
curl -X DELETE https://api.hookbase.app/api/destinations/bulk \
-H "Authorization: Bearer whr_your_api_key" \
-H "Content-Type: application/json" \
-d '{"ids": ["dst_abc123", "dst_def456"]}'Response
{
"success": true,
"deleted": 2
}Warning
Deleting destinations removes them from all routes. Delivery history is preserved.
Error Responses
400 Bad Request
Invalid URL:
{
"error": "Bad Request",
"message": "Invalid URL format",
"code": "INVALID_URL"
}Invalid warehouse config:
{
"error": "Bad Request",
"message": "Invalid warehouse configuration: bucket must be 3-63 characters"
}403 Forbidden
Plan restriction:
{
"error": "Forbidden",
"message": "Warehouse destinations require Pro or Business plan."
}404 Not Found
Destination not found:
{
"error": "Not Found",
"message": "Destination with ID dst_xyz not found",
"code": "RESOURCE_NOT_FOUND"
}