Skip to main content
Documentation

Notification Sinks

Notification sinks let you receive alerts when tasks complete, are cancelled, or fail. HPI supports three sink types: webhooks (HTTP POST), email (with PDF attachment), and NATS (message publish).

Setting Up Webhooks

Add a webhook sink when creating a task:

{
  "title": "Review document",
  "sinks": [{
    "type": "webhook",
    "url": "https://your-app.com/webhooks/task-complete",
    "events": ["completed", "cancelled", "failed"]
  }],
  "steps": [...]
}

If you don't provide a secret, one is auto-generated and returned in the response. Store it to verify webhook signatures.

Webhook Payload

{
	"source": "hpi",
	"event": "task.completed",
	"task_id": "a1b2c3d4-...",
	"correlation_key": "your-corr-id",
	"timestamp": "2026-02-24T12:05:00Z",
	"data": {
		"decision": "Approve",
		"comments": "Looks good!"
	}
}

Event Types

EventWhen
task.completedOperator submitted the task
task.cancelledTask was cancelled
task.failedTask failed

For cancelled/failed events, a reason field is included instead of data.

Webhook Headers

Content-Type: application/json
X-Webhook-Event: task.completed
X-Webhook-Task-Id: a1b2c3d4-...
X-Webhook-Signature: sha256=abc123...

Signature Verification

Verify webhooks by computing an HMAC-SHA256 of the raw request body using the webhook secret:

import hmac
import hashlib

def verify_webhook(body: bytes, secret: str, signature_header: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header)
const crypto = require('crypto');

function verifyWebhook(body, secret, signatureHeader) {
	const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(body).digest('hex');
	return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));
}

Retry Behavior

Failed webhook deliveries are retried automatically:

AttemptDelay
1stImmediate
2nd5 seconds
3rd30 seconds

Each attempt has a 10-second timeout. After 3 failed attempts, the webhook is abandoned.

Email Sink

Send an email notification when a task completes, is cancelled, or fails. On completion, a PDF of the submitted form data is generated and attached to the email.

{
	"type": "email",
	"to": "user@example.com",
	"events": ["completed"]
}
FieldTypeRequiredDescription
typestringYesMust be "email"
tostringYesRecipient email address
eventsarrayNoEvents to notify on (default: all)

Behavior by event:

  • completed — Email includes a PDF attachment with the full submitted form data
  • cancelled / failed — Email is sent without attachment; includes the cancellation or failure reason
Note: Email sinks require SMTP to be configured on the server.

NATS Sink

Publish an event to a NATS subject when a task completes, is cancelled, or fails. The message is published as an ExternalSignal envelope.

{
	"type": "nats",
	"subject": "my.custom.subject",
	"events": ["completed"]
}
FieldTypeRequiredDescription
typestringYesMust be "nats"
subjectstringYesNATS subject to publish to
eventsarrayNoEvents to notify on (default: all)