InvestiFiPartner APIBeta
Prod Environment

KYC Status Change Event

Delivers a user's identity verification status change to your callback URL.

Sent to every callback URL subscribed to the kyc event type when a user's status changes for one of your financial institution's investing products. Intermediate states carrying no outcome you can act on are not delivered.

One subscription covers every delivered status: filter on data.kyc_status (pending, document_requested, approved, rejected, closed, account_takeover) rather than subscribing per status. A user who has finished onboarding into a product reports approved for that product, named in data.product.

Each request carries two headers:

  • X-InvestiFi-Webhook-Id: the delivery's idempotency key, equal to event_id and reused across retries. Deduplicate on it.
  • X-InvestiFi-Webhook-Signature: t=<unix_seconds>,v1=<hex digest>. The digest is a hash-based message authentication code (HMAC-SHA256) over the timestamp, a period, and the raw request body, keyed by the signing secret returned from your first subscribe. v1 is a scheme tag: match on it rather than assuming one value. The header is sent once your financial institution has a signing secret.

Verify against the raw request body, before parsing it, so the bytes match what was signed. Compare digests in constant time:

import hashlib
import hmac

parts = dict(p.split("=", 1) for p in signature_header.split(","))
signed = f"{parts['t']}.{raw_body.decode()}".encode()
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, parts["v1"]):
    raise ValueError("Signature does not match")

Delivery is at-least-once. Return any 2xx status to acknowledge; a non-2xx response or a timeout is retried. links.self points at the authoritative user record for consumers that would rather refetch than trust the payload.

Each subscription is pinned to the API version it was created through, and links.self is built at that version: a subscription created via the v1 subscribe endpoint emits /v1/... links, and keeps doing so after newer API versions ship. When you migrate to a new API version, switch both at the same time: point your API calls at the new base URL and re-create your webhook subscriptions through the new version's subscribe endpoint, then delete the old subscriptions.

Parameters
body
The envelope POSTed to a subscribed callback URL.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

Example Requests

The envelope delivered to a partner callback URL.

Every webhook shares this shape: data is a convenience so a partner can act without a callback, and links.self keeps the API the source of truth for consumers that would rather refetch.

POST/kyc