secretKey — store this securely, as it is used to verify the authenticity of every webhook delivery sent to your endpoint.
Request
POST /public/webhook/subscribe
Headers
Must be
application/json.Must be
application/x-www-form-urlencoded.Your API Application Key.
Your User API Key.
Current UTC timestamp in RFC 7231 format (e.g.
Mon, 06 Apr 2026 00:22:19 GMT).HMAC-SHA256 signature of the canonical request, Base64-encoded.
Body Parameters
Absolute HTTPS URL that will receive webhook POST payloads. Must use the
https:// scheme and resolve to a publicly routable host. Private, loopback, and link-local addresses are rejected. The value is trimmed before storage.Comma-separated list of event type strings to subscribe to (e.g.
ProposalStatusChanged,ProposalBuildStatusChanged). See the Webhook Events reference for all available event types.Optional human-readable label for this subscription. Useful when managing multiple subscriptions.
Response
200 Success
Unique numeric identifier of the newly created webhook subscription. Use this ID in update and delete requests.
The HTTPS callback URL that will receive event payloads.
The description label, if provided.
Whether the subscription is currently active. Newly created subscriptions are enabled by default.
HMAC secret used to sign webhook deliveries. Store this value securely. Verify incoming requests by computing
HMAC_SHA256(secretKey, timestamp + "." + requestBody) and comparing to the v1 value in the X-Webhook-Signature header.Array of event type strings this subscription is registered for.
Error Codes
| Code | Meaning |
|---|---|
| 400 | Validation failed. Common causes: URL is not HTTPS or resolves to a private address, unrecognized event names. |
| 401 | HMAC signature validation failed or credentials are invalid. |
| 402 | An active Portal.io subscription is required to use this endpoint. |
| 403 | Your user account does not have permission for this action. |