ImportOS · Docs
API reference

POST /v1/webhooks

Subscribe a URL to events

Subscribe a URL to events

Creates a subscription for deal.stage_changed, payment.received, document.signed, lead.created and shipment.updated. The response contains the signing secret ONCE. Not idempotent by design (the secret must not be stored for replay): list subscriptions before retrying. At most 20 subscriptions per tenant. Requires scope write:deals. Every delivery is a POST with a JSON body and the headers X-Signature: t=<unix-seconds>,v1=<hex> and X-Event-Id: <uuid>. v1 = hex(HMAC_SHA256(secret, ${t}.${rawBody})) where secret is the whsec_... value returned when the subscription was created and rawBody is the exact request body bytes (do not re-serialize the JSON). Reject the request if |now - t| > 300 s (replay protection) or if no v1 value matches (compare in constant time). During secret rotation several v1= values can be present: accept if any matches. Answer with any 2xx within 8 seconds. Other statuses, timeouts and network errors are retried with exponential backoff (1, 2, 4 ... minutes, up to 6 attempts) and then marked dead; X-Event-Id (= body.id) is stable across retries: use it to deduplicate. Only https URLs on public hosts are accepted. The body is { id, type, tenantId, createdAt, data } (plus informational fields); data carries identifiers and public fields only (no margins, no personal data). A ready-made verifier is exported by the SDK: import { verifyWebhookSignature } from "@importos/sdk/webhooks".

  • Authentication: header Authorization: Bearer rv_live_... (API keys and scopes)
  • Required scope: write:deals
Descriptions of the operation, parameters and fields come from the OpenAPI specification (openapi.json).

Request body

FieldTypeRequiredDescription
urlstring (uri)yesHTTPS endpoint that receives POST requests. Private/internal hosts are rejected.
events"deal.stage_changed" | "payment.received" | "document.signed" | "lead.created" | "shipment.updated"[]yesEvents to receive.
descriptionstring | nullno

Responses

201

The subscription and its secret (shown once).

application/json · Schema: WebhookCreated

FieldTypeRequiredDescription
webhookobjectyes
webhook.idstring (uuid)yes
webhook.urlstringyes
webhook.descriptionstring | nullyes
webhook.eventsstring[]yes
webhook.enabledbooleanyes
webhook.secretPrefixstring | nullyesFirst characters of the signing secret, to tell secrets apart. The full secret is never shown again.
webhook.failureCountintegeryes
webhook.lastSuccessAtstring | nullyesISO 8601 date-time (UTC).
webhook.lastFailureAtstring | nullyesISO 8601 date-time (UTC).
secretstringyesSigning secret (whsec_...). Shown ONCE, store it now. Use it to verify X-Signature.

400

Invalid request parameters or body (code validation_error).

application/problem+json · Schema: Problem

401

Missing, malformed, unknown, revoked or expired API key (code unauthorized).

application/problem+json · Schema: Problem

403

The API key lacks the scope required by this endpoint (code insufficient_scope).

application/problem+json · Schema: Problem

409

Subscription limit reached (webhook_limit).

application/problem+json · Schema: Problem

422

The URL is not acceptable: not https, private host, credentials in URL (webhook_url_rejected).

application/problem+json · Schema: Problem

429

Rate limit exceeded for the tenant plan (code rate_limited). Wait Retry-After seconds.

application/problem+json · Schema: Problem

On this page