Skip to content

Webhooks ​

Webhooks let you receive real-time HTTP notifications when events occur in your project. Configure a webhook URL and select which events to listen for — Studio will POST a signed payload to your endpoint whenever a matching event fires.

Managed service / Enterprise Edition

Outbound webhooks are an Enterprise Edition feature, gated by the api.webhooks_outbound plan feature. They are available on Contentrain's managed service (Starter plans and above) and on self-hosted Enterprise Edition deployments. They are not available in the self-hosted Community Edition.

Creating a Webhook ​

  1. Open the project settings and go to the Webhooks tab
  2. Click Create webhook
  3. Enter the webhook URL (must be HTTPS for production)
  4. Select the events you want to subscribe to
  5. A webhook secret is generated automatically for signature verification

Creating a webhook: name, endpoint URL, and the event checkboxes for all thirteen event types

WARNING

Webhook URLs must point to public endpoints. Studio blocks requests to private networks (RFC 1918), localhost, link-local addresses, and cloud metadata endpoints for SSRF protection.

Event Types ​

Studio supports thirteen webhook event types:

EventFires When
content.savedA content entry is created or updated
content.deletedA content entry is deleted
model.savedA content model is created or updated
branch.mergedA review branch is merged to main
branch.rejectedA review branch is rejected (deleted)
branch.changes_requestedA reviewer requests changes on a review branch
cdn.build_completeA CDN build finishes successfully
media.uploadedA media asset is uploaded
form.submittedA public form submission is received
comment.submittedA visitor submits a comment
comment.approvedA comment is approved
deploy.triggeredA deploy hook is triggered
schedule.firedA scheduled run fires

Event Payload Format ​

All webhook payloads follow the same structure:

json
{
  "event": "content.saved",
  "projectId": "project-uuid",
  "timestamp": "2026-04-02T10:30:00.000Z",
  "data": {
    "models": ["blog-posts"],
    "locale": "en",
    "source": "api"
  }
}

The envelope is always { event, projectId, timestamp, data }. The data field varies by event type and contains event-specific information. Most events include a source field (api, conversation, etc.) indicating how the change was made.

Event-Specific Data ​

content.saved:

json
{
  "models": ["blog-posts"],
  "locale": "en",
  "source": "api"
}

content.deleted:

json
{
  "models": ["blog-posts"],
  "locale": "en",
  "entryIds": ["a1b2c3d4e5f6", "g7h8i9j0k1l2"],
  "source": "conversation"
}

model.saved:

json
{
  "modelId": "blog-posts",
  "source": "api"
}

branch.merged:

json
{
  "branch": "cr/content/blog-posts/en/1774800862-27c1",
  "source": "api"
}

cdn.build_complete:

json
{
  "buildId": "build-uuid",
  "status": "success",
  "filesUploaded": 15,
  "durationMs": 3200,
  "error": null
}

media.uploaded:

json
{
  "assetId": "asset-uuid",
  "filename": "hero-banner.webp",
  "contentType": "image/webp"
}

form.submitted:

json
{
  "submissionId": "submission-uuid",
  "modelId": "contact-form",
  "status": "pending"
}

Webhook Security ​

HMAC-SHA256 Signatures ​

Every webhook delivery includes a signature in the X-Contentrain-Signature header. The signature is an HMAC-SHA256 hash of the request body using your webhook secret.

To verify a webhook delivery:

javascript
import { createHmac, timingSafeEqual } from 'crypto'

function verifyWebhook(body, signature, secret) {
  const expected = createHmac('sha256', secret)
    .update(body)
    .digest('hex')

  return timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  )
}

WARNING

Always verify webhook signatures before processing the payload. Use timing-safe comparison to prevent timing attacks.

SSRF Protection ​

Studio validates webhook URLs to prevent Server-Side Request Forgery:

  • Blocked: localhost, 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, ::1, cloud metadata endpoints
  • Required: http:// or https:// protocol
  • Recommended: Use HTTPS in production

Test Delivery ​

You can send a test delivery to verify your webhook configuration:

  1. Open the webhook in settings
  2. Click Test
  3. Studio sends a test payload to your endpoint
  4. View the delivery result (status code, response time)

Delivery Logs ​

Every webhook delivery is logged. View the delivery history to see:

FieldDescription
Event typeWhich event triggered the delivery
Status codeHTTP response code from your endpoint
Response timeHow long the delivery took
TimestampWhen the delivery was attempted
PayloadThe data that was sent

Retry Behavior ​

If a webhook delivery fails (non-2xx response or timeout), Studio retries with exponential backoff:

AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
612 hours

After 5 failed retries, the delivery is marked as permanently failed. You can view failed deliveries in the delivery logs.

TIP

Ensure your webhook endpoint responds quickly (under 10 seconds) with a 2xx status code. Return 200 OK as soon as you receive the payload, then process it asynchronously.

Managing Webhooks ​

Editing a Webhook ​

You can update a webhook's URL, events, or active status:

  1. Open webhook settings
  2. Click on the webhook to edit
  3. Modify the URL or event subscriptions
  4. Save changes

Deleting a Webhook ​

To remove a webhook:

  1. Open webhook settings
  2. Click the delete button on the webhook
  3. Confirm the deletion

Deleting a webhook stops all future deliveries immediately.

Plan Limits ​

FeatureFreeStarterProEnterprise
Outbound webhooks0310Unlimited

Use Cases ​

ScenarioEventsAction
Rebuild static sitebranch.mergedTrigger CI/CD pipeline
Notify Slack on new contentcontent.savedPost to Slack channel
Invalidate CDN cachecdn.build_completePurge cache keys
Process form submissionsform.submittedSend to CRM or email
Sync search indexcontent.saved, content.deletedUpdate Algolia/Typesense
Audit trailAll eventsLog to monitoring service

Next Steps ​

  • CDN — Deliver content through the built-in CDN
  • Forms — Accept and manage form submissions
  • Conversation API — Programmatic content management

Released under the AGPL-3.0 License.