Webhooks
Webhooks let you receive real-time HTTP callbacks when events occur in your organization. You can subscribe to specific event types and graph8 will POST a signed JSON payload to your endpoint.
Available Events
GET /webhooks/events
Returns all event types you can subscribe to.
Example
curl "https://api.graph8.com/api/v1/webhooks/events" \ -H "Authorization: Bearer $API_KEY"Response
{ "data": [ { "event": "campaign.created" }, { "event": "campaign.updated" }, { "event": "campaign.deleted" }, { "event": "campaign.launched" }, { "event": "campaign.status_changed" }, { "event": "document.created" }, { "event": "document.updated" }, { "event": "document.generated" }, { "event": "intelligence.completed" }, { "event": "research.completed" }, { "event": "company.enriched" }, { "event": "person.enriched" }, { "event": "company_intelligence.completed" } ]}List Webhooks
GET /webhooks
Returns all webhook subscriptions for your organization.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
is_active | boolean | — | Filter by active status |
Example
curl "https://api.graph8.com/api/v1/webhooks" \ -H "Authorization: Bearer $API_KEY"response = requests.get( f"{BASE_URL}/webhooks", headers=HEADERS)Response
{ "data": [ { "id": "wh-abc", "name": "CRM Sync", "url": "https://example.com/webhooks/graph8", "events": ["campaign.created", "campaign.updated"], "is_active": true, "created_at": "2026-02-20T10:00:00", "updated_at": "2026-02-20T10:00:00" } ]}Create Webhook
POST /webhooks
Create a new webhook subscription. The signing secret is returned only once in the response — store it securely.
Maximum 10 active webhooks per organization.
Returns 201 Created.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Target URL for delivery |
events | string[] | Yes | Event types to subscribe to |
name | string | No | Human-readable name |
Example
curl -X POST "https://api.graph8.com/api/v1/webhooks" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/webhooks/graph8", "events": ["campaign.created", "campaign.launched"], "name": "CRM Sync" }'response = requests.post( f"{BASE_URL}/webhooks", headers=HEADERS, json={ "url": "https://example.com/webhooks/graph8", "events": ["campaign.created", "campaign.launched"], "name": "CRM Sync" })secret = response.json()["data"]["secret"] # Store this!Response
{ "data": { "id": "wh-abc", "name": "CRM Sync", "url": "https://example.com/webhooks/graph8", "events": ["campaign.created", "campaign.launched"], "is_active": true, "secret": "whsec_a1b2c3d4e5f6..." }}Verifying Signatures
Each delivery includes an X-Webhook-Signature header. Verify it with HMAC-SHA256:
import hashlib, hmac
def verify_signature(payload: bytes, signature: str, secret: str) -> bool: expected = hmac.new( secret.encode(), payload, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, signature)Get Webhook
GET /webhooks/{webhook_id}
Returns webhook details. The secret is not included in the response.
Update Webhook
PATCH /webhooks/{webhook_id}
Partial update — send only the fields you want to change.
Request Body
| Field | Type | Description |
|---|---|---|
url | string | Target URL |
events | string[] | Event types |
name | string | Human-readable name |
is_active | boolean | Enable or disable |
Delete Webhook
DELETE /webhooks/{webhook_id}
Returns 204 No Content on success.
List Deliveries
GET /webhooks/{webhook_id}/deliveries
Returns delivery attempts for a webhook, with pagination.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 50 | Items per page (max 200) |
status | string | — | Filter by delivery status (success, failed, pending) |
Example
curl "https://api.graph8.com/api/v1/webhooks/wh-abc/deliveries" \ -H "Authorization: Bearer $API_KEY"Response
{ "data": [ { "id": "del-1", "event": "campaign.created", "status": "success", "attempts": 1, "max_attempts": 3, "response_code": 200, "error_message": null, "created_at": "2026-02-25T10:00:00", "completed_at": "2026-02-25T10:00:01" } ], "pagination": { "page": 1, "limit": 50, "total": 1, "has_next": false }}Failed deliveries are retried up to 3 times with increasing delays (10s, 60s, 300s).