Playground ↗ Postman ↗ Dashboard ↗
POST /v2/webhooks

Register a webhook

Registers a URL that Nuton will POST to whenever an event you’ve subscribed to fires. Webhooks are scoped to your tenant — they receive events for every user under your API key.

Request

Headers

HeaderRequiredNotes
X-API-Keyyes
Content-Typeyesapplication/json

Note: Webhook registration is a tenant-level operation — no X-External-User-Id needed.

Body

url string (URL) required
HTTPS endpoint Nuton will POST events to. Max 2048 characters.
events string[] default ["course.completed", "course.failed", "job.progress"]
Event types to subscribe to. See Event types.

Returns

{
  "id": "wh_01HW0XYZ…",
  "url": "https://example.com/hooks/nuton",
  "events": ["course.completed", "course.failed"],
  "active": true,
  "secret": "whsec_2YmW…dXk",
  "created_at": "2026-05-19T14:11:00Z"
}

Store secret immediately. It’s the only time it’s returned. Use it to verify the X-Nuton-Signature header on every incoming webhook delivery (HMAC-SHA256 of the raw request body).

Verifying deliveries

Every webhook POST from Nuton includes:

  • Content-Type: application/json
  • X-Nuton-Event: <event_type> — the event name (e.g. course.completed)
  • X-Nuton-Signature: <hex> — HMAC-SHA256 of the raw body, using your webhook’s secret

Example verification in Python:

import hmac, hashlib

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

Errors

  • 422url is not HTTPS, or events contains an unknown event type.