Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.topify.ai/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks let you receive real-time notifications when action workflows reach checkpoints or complete. They are required for the execute workflow used by new_content actions.

Register webhook

POST /webhooks
Register a new webhook endpoint to receive event notifications.

Request body

FieldTypeRequiredDescription
urlstringYesHTTPS endpoint URL that will receive webhook events
eventsstring[]YesArray of event types to subscribe to

Valid events

EventDescription
action.checkpointWorkflow paused at an approval checkpoint (outline, draft, or final review)
action.completedWorkflow finished successfully
action.failedWorkflow encountered an error
curl -X POST "https://topify-customer-api-production.up.railway.app/api/public/v1/webhooks" \
  -H "X-API-Key: tk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks/topify",
    "events": ["action.checkpoint", "action.completed", "action.failed"]
  }'

Response (201 Created)

{
  "success": true,
  "data": {
    "id": "wh_a1b2c3d4-...",
    "url": "https://example.com/webhooks/topify",
    "events": ["action.checkpoint", "action.completed", "action.failed"],
    "is_active": true,
    "secret": "whsec_k7m9p2...",
    "created_at": "2026-04-08T12:00:00Z"
  }
}
The secret field is only returned once at creation time. Store it securely — you will need it to verify webhook signatures.

Error responses

StatusCause
400Missing url, non-HTTPS URL, empty events array, or invalid event type
403API key has read-only access
409A webhook with this URL already exists

List webhooks

GET /webhooks
Returns all registered webhooks for your account.
curl "https://topify-customer-api-production.up.railway.app/api/public/v1/webhooks" \
  -H "X-API-Key: tk_live_..."

Response

{
  "success": true,
  "data": [
    {
      "id": "wh_a1b2c3d4-...",
      "url": "https://example.com/webhooks/topify",
      "events": ["action.checkpoint", "action.completed", "action.failed"],
      "is_active": true,
      "created_at": "2026-04-08T12:00:00Z"
    }
  ]
}
The secret field is not included in list responses. It is only returned when the webhook is first created.

Delete webhook

DELETE /webhooks/{webhook_id}
Permanently remove a webhook. Events will no longer be delivered to the endpoint.

Path parameters

ParamTypeDescription
webhook_idstringThe webhook ID
curl -X DELETE "https://topify-customer-api-production.up.railway.app/api/public/v1/webhooks/{webhook_id}" \
  -H "X-API-Key: tk_live_..."

Response

{
  "success": true,
  "data": {
    "id": "wh_a1b2c3d4-...",
    "message": "Webhook deleted successfully"
  }
}

Error responses

StatusCause
403API key has read-only access
404Webhook not found

Webhook payload format

When an event fires, Topify sends a POST request to your registered URL with the following JSON body.

action.checkpoint payload

{
  "event": "action.checkpoint",
  "timestamp": "2026-04-08T21:19:13.463Z",
  "data": {
    "action_id": "a1b2c3d4-...",
    "workflow_id": "w1x2y3z4-...",
    "checkpoint": "outline",
    "content": "## Article Outline\n\n1. Introduction to project management tools...",
    "options": [
      { "action": "approve", "label": "Approve & Write" },
      { "action": "edit", "label": "Edit Outline" },
      { "action": "regenerate", "label": "Regenerate" },
      { "action": "reject", "label": "Cancel" }
    ]
  }
}

action.completed payload

{
  "event": "action.completed",
  "timestamp": "2026-04-08T21:25:00.000Z",
  "data": {
    "action_id": "a1b2c3d4-...",
    "workflow_id": "w1x2y3z4-...",
    "result": {
      "title": "Best Project Management Tools in 2026",
      "content": "..."
    }
  }
}

action.failed payload

{
  "event": "action.failed",
  "timestamp": "2026-04-08T21:22:00.000Z",
  "data": {
    "action_id": "a1b2c3d4-...",
    "workflow_id": "w1x2y3z4-...",
    "error": "LLM generation timed out after 120 seconds"
  }
}

Payload fields

FieldTypeDescription
eventstringEvent type (action.checkpoint, action.completed, action.failed)
timestampstringISO 8601 timestamp of when the event occurred
data.action_idstring (UUID)The action that triggered the event
data.workflow_idstring (UUID)The active workflow ID
data.checkpointstringCheckpoint name (only for action.checkpoint)
data.contentstringContent to review (only for action.checkpoint)
data.optionsobject[]Available response actions (only for action.checkpoint)
data.resultobjectFinal output (only for action.completed)
data.errorstringError message (only for action.failed)

Verifying signatures

Every webhook request includes an X-Webhook-Signature header containing an HMAC-SHA256 signature of the raw request body, computed using the webhook secret returned at creation time. Always verify this signature before processing the payload to ensure requests are authentic.
import hmac
import hashlib

def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

# In your webhook handler:
signature = request.headers["X-Webhook-Signature"]
is_valid = verify_webhook(request.body, signature, WEBHOOK_SECRET)
Your endpoint should return a 200 status code within 10 seconds. If your endpoint fails to respond or returns a non-2xx status, Topify will retry up to 3 times with exponential backoff.