Skip to main content

Documentation Index

Fetch the complete documentation index at: https://api-docs.hrizn.io/llms.txt

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

Instead of polling for status, webhooks push events to your server as they happen.

Webhook Delivery Flow

This sequence diagram shows the full lifecycle of a typical content generation integration using webhooks:

How It Works

1

Register a webhook URL

Select which events to subscribe to when creating the webhook.
2

Receive events

When an event occurs, Hrizn sends an HTTP POST to your URL with a JSON payload.
3

Verify the signature

Your server verifies the HMAC-SHA256 signature in the X-Webhook-Signature header.
4

Process and acknowledge

Process the payload and return a 2xx response. If delivery fails, Hrizn retries with exponential backoff.

Setting Up Webhooks

Via the Dashboard

Go to the API tab in the Dealership Manager, switch to the Webhooks section, and click Add Webhook.

Via the API

curl -X POST https://api.app.hrizn.io/v1/public/webhooks \
  -H "X-API-Key: hzk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhooks/horizn",
    "events": ["content.progress", "content.completed", "ideacloud.completed"]
  }'
The response includes a secret for verifying signatures.
Store the signing secret in a secrets manager or environment variable. It is returned only once at creation time and cannot be retrieved later.

Event Payload

Every webhook delivery sends a JSON payload:
{
  "id": "evt_1707000000000_abc1234",
  "type": "content.completed",
  "site_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "article_id": "a1b2c3d4-...",
    "article_type": "basic"
  },
  "timestamp": "2026-02-10T12:00:00.000Z",
  "api_version": "2025-01-01"
}

Verifying Signatures

Every delivery includes an X-Webhook-Signature header with an HMAC-SHA256 signature of the request body:
X-Webhook-Signature: sha256=abc123def456...
import { createHmac } from "crypto";

function verifyWebhookSignature(body: string, signature: string, secret: string) {
  const expected = createHmac("sha256", secret).update(body).digest("hex");
  return `sha256=${expected}` === signature;
}

// Express middleware
app.post("/webhooks/horizn", (req, res) => {
  const signature = req.headers["x-webhook-signature"];
  const isValid = verifyWebhookSignature(req.rawBody, signature, WEBHOOK_SECRET);

  if (!isValid) {
    return res.status(401).send("Invalid signature");
  }

  const event = JSON.parse(req.rawBody);
  console.log(`Received: ${event.type}`, event.data);

  res.status(200).send("OK");
});

Available Events

EventDescriptionPayload Data
ideacloud.completedIdeaCloud research finishedideacloud_id, keyword
ideacloud.failedIdeaCloud research failedideacloud_id, keyword, error
EventDescriptionPayload Data
content.progressGeneration stage transitionarticle_id, article_type, component_type, stage, message, progress_percent
content.completedContent generation finishedarticle_id, article_type
content.failedContent generation failedarticle_id, article_type, error
EventDescriptionPayload Data
content.approval.submittedContent submitted for approvalarticle_id, article_type, submitted_by
content.approval.approvedContent approved by reviewerarticle_id, article_type, approved_by
content.approval.rejectedContent changes requested by reviewerarticle_id, article_type, rejected_by, reason
content.approval.escalatedContent approval escalated to next reviewerarticle_id, article_type, escalated_to
content.approval.overriddenContent approval overridden by authorized userarticle_id, article_type, overridden_by, reason
EventDescriptionPayload Data
content.publishedContent published and available via publish-data endpointarticle_id, article_type, posting_status
content.unpublishedContent unpublished (reverted to draft)article_id, article_type, posting_status
content.scheduledContent scheduled for future publicationarticle_id, article_type, posting_status
EventDescriptionPayload Data
compliance.completedCompliance check finishedarticle_id, overall_status, overall_score
content_tools.completedContent tools generatedarticle_id, tools
EventDescriptionPayload Data
inventory.description.completedVehicle description generatedvin, year, make, model
inventory.description.batch_completedBatch descriptions finishedcount, site_id
inventory.feed.updatedInventory feed refreshedvehicle_count
GBP posting API endpoints are deprecated and no longer available. These events are retained only for historical webhook payload compatibility.
EventDescriptionPayload Data
gbp.post.publishedDeprecated historical GBP post eventpost_id, location_id, post_type
gbp.post.scheduledDeprecated historical GBP scheduled post eventpost_id, location_id, post_type, publish_at_utc
gbp.post.cancelledDeprecated historical GBP cancelled post eventpost_id, location_id
gbp.post.failedDeprecated historical GBP failed post eventpost_id, location_id, error

Content Progress Events

The content.progress event provides real-time visibility into content generation stages. Unlike terminal events (content.completed, content.failed), progress events fire at meaningful stage transitions — typically 4-6 events per content item.

Stages

StageDescriptionTypical %
researchingVehicle data being fetched (comparisons & model landing pages only)5%
outliningArticle structure being created5%
writingContent generation started10-80%
finalizingPost-processing (links, TOC, formatting)95%

Example Payload

{
  "id": "evt_1707000000000_abc1234",
  "type": "content.progress",
  "site_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "article_id": "a1b2c3d4-...",
    "article_type": "comparison",
    "component_type": "Body",
    "stage": "writing",
    "message": "Writing content...",
    "progress_percent": 45
  },
  "timestamp": "2026-02-10T12:00:05.000Z",
  "api_version": "2025-01-01"
}
Subscribers must explicitly include content.progress in their events array when creating or updating a webhook subscription. Existing subscribers only receiving content.completed will not receive progress events unless they update their subscription.

Retry Policy

If your endpoint returns a non-2xx status or times out (15s), Hrizn retries with exponential backoff:
  • Attempt 1: Immediate
  • Attempt 2: ~1 minute later
  • Attempt 3: ~5 minutes later
  • Attempt 4: ~30 minutes later
  • Attempt 5: ~2 hours later
After 5 failed attempts, the delivery is sent to a dead letter queue.
After 10 consecutive failures across different events, the webhook subscription is automatically disabled. You’ll need to re-enable it from the dashboard or via PATCH /webhooks/{id}.

Testing

Send a test ping to verify your webhook URL:
curl -X POST https://api.app.hrizn.io/v1/public/webhooks/{id}/test \
  -H "X-API-Key: hzk_your_key_here"
This sends a test.ping event to your URL and returns the response status.
Use ngrok or a similar tunneling tool to expose a local development server for testing webhooks without deploying.

Managing Webhooks

ActionMethodEndpoint
CreatePOST/webhooks
ListGET/webhooks
UpdatePATCH/webhooks/{id}
DeleteDELETE/webhooks/{id}
TestPOST/webhooks/{id}/test
DeliveriesGET/webhooks/{id}/deliveries
Last modified on May 7, 2026