Webhooks

Create a webhook subscription

Subscribe an HTTPS endpoint to workspace events.

The signing secret is returned exactly once, in this response. It is stored encrypted with AES-256-GCM and is never returned again by any endpoint, including GET /webhooks/{webhookId}. If it is lost, delete the subscription and create a new one. The secret is 32 random bytes rendered as 64 hex characters.

Verifying a delivery. Each delivery arrives as a POST carrying X-InkSeal-Signature: v1=<hex>, X-InkSeal-Timestamp: <unix seconds>, and X-InkSeal-Event-Id. The signature is HMAC-SHA256 over the exact string <timestamp>.<raw request body>, keyed by the secret, hex-encoded. Recompute it over the unparsed body, compare in constant time, and reject a timestamp that is too far from now. Delivery is at-least-once, so deduplicate on X-InkSeal-Event-Id, which is derived from the state transition and is stable across automatic retries and manual ones.

Target URL restrictions. The URL must be https://; anything else is refused. It is then resolved through DNS and checked, and the request is refused with 400 invalid_url when the host is localhost, 127.0.0.1, or ::1, when it fails to resolve at all, or when any resolved address falls in a private or reserved range: IPv4 10.0.0.0/8, 127.0.0.0/8, 0.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16, and IPv6 ::1, fc00::/7, and fe80::/10. The same check runs again at delivery time, so a hostname that is later repointed at a private address stops being delivered to rather than being used as an internal proxy.

events may be an explicit list of event names, or null to subscribe to every event including future ones. A workspace holds at most 5 subscriptions; exceeding that answers 409 limit_exceeded.

Accepts an Idempotency-Key. A retry with the same key replays the original response, including the one-time secret, instead of creating a second subscription.

post/webhooks

Request

  • Base URL: https://inkseal.net/api/v1
  • URL: https://inkseal.net/api/v1/webhooks
  • Auth: HTTP bearer

Headers

Idempotency-Keystring

Makes this mutation retry-safe. 1 to 255 printable ASCII characters (0x20 to 0x7e), trimmed before use. The key is scoped to the workspace and the credential that sent it. Reusing it with a different method, path, or payload answers 422 idempotency_key_reuse. A completed attempt replays its stored status and body with an Idempotent-Replay: true response header; 5xx, 429, and non-JSON answers leave the key retryable. A concurrent request holding the 90 second lease answers 409 idempotency_in_progress. Records are retained 24 hours.

Request body

urlstring uri required

The endpoint to POST deliveries to. Must be https://. Rejected with 400 invalid_url when it is localhost, fails to resolve, or resolves to a private or reserved address.

eventsWebhookSubscriptionEventType[] nullable required

The events to subscribe to, at least one and each named at most once, or null to subscribe to every event including ones added later.

Example request

{
  "url": "https://hooks.example.com/inkseal",
  "events": [
    "envelope.completed",
    "signer.signed",
    "envelope.send_failed"
  ]
}

Response

The subscription, plus the only copy of its signing secret that will ever be returned.

Example response

{
  "data": {
    "id": "kQ7fN2wYb0LxTs6RaVpEu",
    "url": "https://hooks.example.com/inkseal",
    "events": [
      "envelope.completed",
      "signer.signed",
      "envelope.send_failed"
    ],
    "secret": "REDACTEDREDACTEDREDACTEDREDACTEDREDACTEDREDACTEDREDACTEDREDACTED"
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.