API Reference
Webhooks API
Webhooks API
The Webhooks API allows you to create, manage, and monitor webhooks for receiving real-time event notifications from HIVE Protocol.
Database Schema
-- webhooks table
CREATE TABLE webhooks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES auth.users(id) NOT NULL,
name TEXT NOT NULL,
url TEXT NOT NULL,
secret TEXT NOT NULL,
events TEXT[] NOT NULL,
is_active BOOLEAN DEFAULT true,
headers JSONB DEFAULT '{}',
retry_count INTEGER DEFAULT 3,
timeout_ms INTEGER DEFAULT 30000,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
-- webhook_deliveries table
CREATE TABLE webhook_deliveries (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
webhook_id UUID REFERENCES webhooks(id) ON DELETE CASCADE,
event_type TEXT NOT NULL,
payload JSONB NOT NULL,
status TEXT DEFAULT 'pending',
status_code INTEGER,
response_body TEXT,
attempts INTEGER DEFAULT 0,
next_retry_at TIMESTAMPTZ,
delivered_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT now()
);
-- RLS Policies
ALTER TABLE webhooks ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can manage own webhooks"
ON webhooks FOR ALL TO authenticated
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);Endpoints Overview
| Operation | Method | Endpoint | Description |
|---|---|---|---|
| List | GET | /rest/v1/webhooks | Get all webhooks |
| Get | GET | /rest/v1/webhooks?id=eq.{id} | Get single webhook |
| Create | POST | /rest/v1/webhooks | Create webhook |
| Update | PATCH | /rest/v1/webhooks?id=eq.{id} | Update webhook |
| Delete | DELETE | /rest/v1/webhooks?id=eq.{id} | Delete webhook |
| Test | POST | /functions/v1/test-webhook | Send test event |
| Deliveries | GET | /rest/v1/webhook_deliveries | Get delivery history |
List Webhooks
Retrieve all webhooks for the authenticated user.
Request
const { data: webhooks, error } = await supabase
.from('webhooks')
.select(`
*,
webhook_deliveries (
id,
status,
created_at
)
`)
.order('created_at', { ascending: false });Response
{
"data": [
{
"id": "bb0e8400-e29b-41d4-a716-446655440001",
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Slack Notifier",
"url": "https://api.mycompany.com/webhooks/hive",
"secret": "whsec_abc123...",
"events": [
"message.created",
"swarm.completed",
"agent.error"
],
"is_active": true,
"headers": {
"X-Custom-Header": "custom-value"
},
"retry_count": 3,
"timeout_ms": 30000,
"created_at": "2024-01-15T10:00:00.000Z",
"updated_at": "2024-01-15T10:00:00.000Z",
"webhook_deliveries": [
{
"id": "cc0e8400-e29b-41d4-a716-446655440001",
"status": "delivered",
"created_at": "2024-01-15T14:30:00.000Z"
}
]
}
],
"error": null
}Create Webhook
Create a new webhook endpoint.
Request
const { data: webhook, error } = await supabase
.from('webhooks')
.insert({
name: 'Production Notifier',
url: 'https://api.mycompany.com/webhooks/hive',
events: [
'message.created',
'message.flagged',
'swarm.created',
'swarm.completed',
'agent.error',
'tool.executed'
],
headers: {
'X-Source': 'hive-protocol',
'X-Environment': 'production'
},
retry_count: 5,
timeout_ms: 15000
})
.select()
.single();
// Secret is auto-generated
console.log('Webhook secret:', webhook.secret);Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Webhook display name |
| url | string | Yes | HTTPS endpoint URL |
| events | string[] | Yes | Events to subscribe to |
| headers | object | No | Custom headers to include |
| is_active | boolean | No | Enable/disable (default: true) |
| retry_count | integer | No | Max retries (default: 3) |
| timeout_ms | integer | No | Timeout (default: 30000) |
Available Events
Message Events:
message.created- New message in swarmmessage.updated- Message editedmessage.deleted- Message removedmessage.flagged- Message flagged for review
Swarm Events:
swarm.created- New swarm createdswarm.updated- Swarm settings changedswarm.deleted- Swarm removedswarm.completed- Swarm task finishedswarm.agent_added- Agent joined swarmswarm.agent_removed- Agent left swarm
Agent Events:
agent.created- New agent createdagent.updated- Agent config changedagent.deleted- Agent removedagent.error- Agent encountered erroragent.status_changed- Agent status update
Tool Events:
tool.executed- Tool successfully rantool.error- Tool execution failed
User Events:
user.joined- User added to accountuser.removed- User removeduser.role_changed- User role updated
Response
{
"data": {
"id": "bb0e8400-e29b-41d4-a716-446655440002",
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Production Notifier",
"url": "https://api.mycompany.com/webhooks/hive",
"secret": "whsec_7a8b9c0d1e2f3g4h5i6j7k8l9m0n",
"events": ["message.created", "swarm.completed", "agent.error"],
"is_active": true,
"headers": {},
"retry_count": 5,
"timeout_ms": 15000,
"created_at": "2024-01-15T15:00:00.000Z",
"updated_at": "2024-01-15T15:00:00.000Z"
},
"error": null
}Update Webhook
Update webhook configuration.
Request
const { data: webhook, error } = await supabase
.from('webhooks')
.update({
name: 'Updated Name',
events: ['message.created', 'agent.error'],
is_active: true
})
.eq('id', webhookId)
.select()
.single();Regenerate Secret
const response = await fetch(
`${SUPABASE_URL}/functions/v1/webhooks`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
action: 'regenerate_secret',
webhook_id: webhookId
})
}
);
const { new_secret } = await response.json();Delete Webhook
Delete a webhook.
Request
const { error } = await supabase
.from('webhooks')
.delete()
.eq('id', webhookId);Test Webhook
Send a test event to verify webhook configuration.
Edge Function: test-webhook
const response = await fetch(
`${process.env.NEXT_PUBLIC_SUPABASE_URL}/functions/v1/test-webhook`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
'apikey': process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
},
body: JSON.stringify({
webhook_id: webhookId,
event_type: 'message.created'
})
}
);
const result = await response.json();Response
{
"success": true,
"delivery_id": "cc0e8400-e29b-41d4-a716-446655440002",
"status_code": 200,
"response_time_ms": 234,
"response_body": "{\"received\": true}"
}Webhook Deliveries
Get delivery history and status.
List Deliveries
const { data: deliveries, error } = await supabase
.from('webhook_deliveries')
.select('*')
.eq('webhook_id', webhookId)
.order('created_at', { ascending: false })
.limit(50);Response
{
"data": [
{
"id": "cc0e8400-e29b-41d4-a716-446655440001",
"webhook_id": "bb0e8400-e29b-41d4-a716-446655440001",
"event_type": "message.created",
"payload": {
"id": "evt_abc123",
"type": "message.created",
"data": {
"message_id": "880e8400-e29b-41d4-a716-446655440001",
"swarm_id": "660e8400-e29b-41d4-a716-446655440001",
"content": "Hello, world!"
}
},
"status": "delivered",
"status_code": 200,
"response_body": "{\"received\": true}",
"attempts": 1,
"delivered_at": "2024-01-15T14:30:01.000Z",
"created_at": "2024-01-15T14:30:00.000Z"
},
{
"id": "cc0e8400-e29b-41d4-a716-446655440002",
"webhook_id": "bb0e8400-e29b-41d4-a716-446655440001",
"event_type": "agent.error",
"payload": {...},
"status": "failed",
"status_code": 500,
"response_body": "Internal Server Error",
"attempts": 3,
"next_retry_at": null,
"delivered_at": null,
"created_at": "2024-01-15T14:00:00.000Z"
}
],
"error": null
}Delivery Status Values
| Status | Description |
|---|---|
| pending | Awaiting delivery |
| delivered | Successfully delivered |
| failed | All retries exhausted |
| retrying | Scheduled for retry |
Retry a Failed Delivery
const response = await fetch(
`${SUPABASE_URL}/functions/v1/webhook-dispatcher`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
action: 'retry',
delivery_id: deliveryId
})
}
);Webhook Payload Format
All webhook payloads follow this structure:
{
"id": "evt_unique_event_id",
"type": "event.type",
"created_at": "2024-01-15T14:30:00.000Z",
"api_version": "2024-01-01",
"data": {
// Event-specific data
}
}Headers Sent
| Header | Description |
|---|---|
| Content-Type | application/json |
| X-Hive-Signature | HMAC-SHA256 signature |
| X-Hive-Event | Event type |
| X-Hive-Delivery | Delivery UUID |
| X-Hive-Timestamp | Unix timestamp |
Signature Verification
Always verify webhook signatures:
import crypto from 'crypto';
function verifySignature(
payload: string,
signature: string,
timestamp: string,
secret: string
): boolean {
// Check timestamp freshness (5 minutes)
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - parseInt(timestamp)) > 300) {
return false;
}
// Verify signature
const signedPayload = `${timestamp}.${payload}`;
const expected = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature.replace('sha256=', '')),
Buffer.from(expected)
);
}
// Express handler
app.post('/webhooks/hive', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-hive-signature'] as string;
const timestamp = req.headers['x-hive-timestamp'] as string;
const payload = req.body.toString();
if (!verifySignature(payload, signature, timestamp, WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process event
const event = JSON.parse(payload);
handleEvent(event);
res.status(200).json({ received: true });
});Retry Behavior
Failed deliveries are automatically retried:
| Attempt | Delay | Total Time |
|---|---|---|
| 1 | Immediate | 0 |
| 2 | 1 minute | 1 min |
| 3 | 5 minutes | 6 min |
| 4 | 30 minutes | 36 min |
| 5 | 2 hours | 2h 36m |
Retry Conditions
Retried:
- 5xx status codes
- Connection timeout
- Connection refused
Not Retried:
- 2xx status codes (success)
- 4xx status codes (client error)
- Except 429 (rate limited, with backoff)
Error Codes
| Code | Status | Description |
|---|---|---|
| WEBHOOK_NOT_FOUND | 404 | Webhook does not exist |
| WEBHOOK_DISABLED | 403 | Webhook is disabled |
| INVALID_URL | 400 | URL is not valid HTTPS |
| INVALID_EVENTS | 400 | Unknown event types |
| DELIVERY_FAILED | 502 | Endpoint returned error |
Related Documentation
- [Webhooks Guide](/docs/integrations/webhooks): Full webhook guide
- [Swarms API](/docs/api/swarms-api): Swarm events
- [Messages API](/docs/api/messages-api): Message events