Create a webhook

Overview

Register a URL to receive events, choose immediate or batch delivery, and optionally filter which events you want.

Use this once per delivery type: a partner can have one immediate and one batch subscription. You'll get the signing secret in this response and nowhere else automatically; store it now.

You'll need a label, your HTTPS URL, and the delivery type (plus an interval for batch).

Returns the subscription and its secret. Deliveries start with the next matching event. Check your endpoint with Send a test event.

Prerequisites

Base URL

EnvironmentURL
Productionhttps://production-api.shoutaboutus.com
Developmenthttps://development-api.shoutaboutus.com

Endpoint

POST /api/v1/partner/webhooks

Authentication

Partner token

  • Only partner users can call it; other tokens get 403.
  • The subscription is created for the partner behind the token.

Rate limit

This endpoint has no rate limit.

Request parameters

None.

Request body

FieldTypeRequiredDescription
labelstringYesYour name for the subscription. Up to 255 characters.
webhook_urlstringYesYour endpoint's HTTPS URL. Up to 2048 characters.
delivery_kindstringYesimmediate (each event as it happens) or batch (one cache_invalidation ping per location per interval). You can have one of each; a second of the same kind gets 422.
batch_interval_hoursintegerNoHours between batches: 1, 2, 4, 6 or 12. Required when delivery_kind is batch.
eventsarray of stringsNoImmediate only: the events to receive, by value from the events catalogue. Only immediate events can be picked. Left out, [] or null: all immediate events. Ignored on a batch subscription (stored as null).
payload_modestringNoImmediate only: full (default; the review, who did it, and the history entry) or minimal (event name and ids only). A batch subscription is always full.
is_activebooleanNoWhether deliveries start now. Default true.

Request payload

Immediate, with an event filter:

{
  "label": "Production webhook",
  "webhook_url": "https://partner.example.com/hooks/sau",
  "delivery_kind": "immediate",
  "is_active": true,
  "events": [
    "review_pull_connected",
    "review_pull_disconnected",
    "usage.limit_reached"
  ],
  "payload_mode": "full"
}

Batch, every 4 hours:

{
  "label": "Nightly refresh",
  "webhook_url": "https://partner.example.com/hooks/sau-batch",
  "delivery_kind": "batch",
  "batch_interval_hours": 4
}

Response body

The payload is inside data.

FieldTypeDescription
dataobjectThe new subscription.
data.idintegerThe subscription's id (webhookSubscriptionId).
data.partner_company_idintegerYour partner id.
data.labelstringYour name for the subscription.
data.webhook_urlstringWhere deliveries are sent.
data.eventsarray of strings or nullThe event filter. null: all immediate events. Always null on a batch subscription.
data.payload_modestringfull (the review, who did it, and the history entry) or minimal (event name and ids only). Always full on a batch subscription.
data.delivery_kindstringimmediate (each event as it happens) or batch (one cache_invalidation ping per location per interval).
data.batch_interval_hoursinteger or nullHours between batches: 1, 2, 4, 6 or 12. null on an immediate subscription.
data.delivery_labelstringThe delivery type in words: immediate, hourly batch or every N hours.
data.last_batch_dispatched_atstring or nullWhen the last batch was sent (ISO 8601). Set to the creation time for a new batch subscription; null on an immediate one.
data.is_activebooleanWhether deliveries are being sent.
data.hmac_secret_fingerprintstringThe first 16 characters of the SHA-256 hash of the signing secret, so you can tell which secret is current. The secret itself is never returned here.
data.last_succeeded_atstring or nullWhen a delivery last succeeded (ISO 8601), or null.
data.last_failed_atstring or nullWhen a delivery last failed (ISO 8601), or null.
data.last_failure_reasonstring or nullWhy the last delivery failed, or null.
data.consecutive_failure_countintegerFailed deliveries in a row since the last success.
data.created_atstringWhen the subscription was created (ISO 8601).
data.updated_atstringWhen it last changed (ISO 8601).
data.hmac_secretstringThe signing secret. Use it to check the X-SAU-Signature header (sha256= and the HMAC-SHA256 of the request body) on every delivery. Shown here once; store it now.
data.hmac_secret_warningstringA reminder to store the secret.

Response payload

{
  "data": {
    "data": {
      "id": 2,
      "partner_company_id": 5,
      "label": "Production webhook",
      "webhook_url": "https://partner.example.com/hooks/sau",
      "events": [
        "review_pull_connected",
        "review_pull_disconnected",
        "usage.limit_reached"
      ],
      "payload_mode": "full",
      "delivery_kind": "immediate",
      "batch_interval_hours": null,
      "delivery_label": "immediate",
      "last_batch_dispatched_at": null,
      "is_active": true,
      "hmac_secret_fingerprint": "587647e874083b23",
      "last_succeeded_at": null,
      "last_failed_at": null,
      "last_failure_reason": null,
      "consecutive_failure_count": 0,
      "created_at": "2026-06-16T10:23:23+00:00",
      "updated_at": "2026-06-16T10:23:23+00:00",
      "hmac_secret": "<hmac-secret>",
      "hmac_secret_warning": "Store this value securely — it will not be shown again. Use it to verify the X-SAU-Signature header on every incoming delivery."
    }
  }
}

Examples

Success payload

Immediate: see Response payload.

Batch:

{
  "data": {
    "data": {
      "id": 4,
      "partner_company_id": 5,
      "label": "Nightly refresh",
      "webhook_url": "https://partner.example.com/hooks/sau-batch",
      "events": null,
      "payload_mode": "full",
      "delivery_kind": "batch",
      "batch_interval_hours": 4,
      "delivery_label": "every 4 hours",
      "last_batch_dispatched_at": "2026-06-16T10:30:00+00:00",
      "is_active": true,
      "hmac_secret_fingerprint": "335b947fe611b6b2",
      "last_succeeded_at": null,
      "last_failed_at": null,
      "last_failure_reason": null,
      "consecutive_failure_count": 0,
      "created_at": "2026-06-16T10:30:00+00:00",
      "updated_at": "2026-06-16T10:30:00+00:00",
      "hmac_secret": "<hmac-secret>",
      "hmac_secret_warning": "Store this value securely — it will not be shown again. Use it to verify the X-SAU-Signature header on every incoming delivery."
    }
  }
}

Error payload

403 Not a Partner token

{
  "message": "Only partner-admin users can manage webhook subscriptions.",
  "status": "error",
  "errors": []
}

422 Missing fields

{
  "message": "The label field is required. (and 2 more errors)",
  "errors": {
    "label": [
      "The label field is required."
    ],
    "webhook_url": [
      "The webhook url field is required."
    ],
    "delivery_kind": [
      "The delivery kind field is required."
    ]
  }
}

422 Invalid values

{
  "message": "The webhook url field must be a valid URL. (and 4 more errors)",
  "errors": {
    "webhook_url": [
      "The webhook url field must be a valid URL."
    ],
    "delivery_kind": [
      "The selected delivery kind is invalid."
    ],
    "batch_interval_hours": [
      "The selected batch interval hours is invalid."
    ],
    "payload_mode": [
      "The selected payload mode is invalid."
    ],
    "events.0": [
      "The selected events.0 is invalid."
    ]
  }
}

422 Batch event on an immediate subscription

{
  "message": "'review_ingested' is not individually subscribable — it is delivered folded into the batch slot's coalesced 'cache_invalidation' ping. Create a batch subscription (no event filter) to receive it.",
  "errors": {
    "events.0": [
      "'review_ingested' is not individually subscribable — it is delivered folded into the batch slot's coalesced 'cache_invalidation' ping. Create a batch subscription (no event filter) to receive it."
    ]
  }
}

422 You already have one of this kind

{
  "message": "A immediate webhook already exists for this partner. Edit the existing one or delete it first.",
  "errors": {
    "delivery_kind": [
      "A immediate webhook already exists for this partner. Edit the existing one or delete it first."
    ]
  }
}
StatusMeaning
201The subscription was created; store hmac_secret now.
401The token is missing, expired or invalid.
403The token isn't a Partner token.
422A field is missing or invalid, an event isn't in the catalogue or can't be picked, or you already have a subscription of this kind.
500Unexpected server error.

Example request

curl --request POST \
  --url "https://production-api.shoutaboutus.com/api/v1/partner/webhooks" \
  --header 'Authorization: Bearer <bearer-token>' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{"label": "Production webhook", "webhook_url": "https://partner.example.com/hooks/sau", "delivery_kind": "immediate", "is_active": true, "events": ["review_pull_connected", "review_pull_disconnected", "usage.limit_reached"], "payload_mode": "full"}'

Did this page help you?