BlendFi
Webhooks

Endpoint management

Create, list, update, delete webhook endpoints. Rotate secrets without dropping deliveries.

Each organization can register multiple webhook endpoints. Each endpoint has its own URL, its own signing secret, and its own subscription set (which events it wants to receive). This page is the CRUD how-to.

Create an endpoint

POST /v1/webhook_endpoints HTTP/1.1
Authorization: Bearer sk_test_…
Idempotency-Key: <uuid>
Content-Type: application/json

{
  "url": "https://your-app.example.com/blendfi-webhooks",
  "event_types": [
    "conversion.completed",
    "conversion.completed",
    "conversion.failed",
    "user.kyc_approved"
  ],
  "description": "production handler"
}
curl -X POST $BLENDFI_BASE/v1/webhook_endpoints \
  -H "Authorization: Bearer $BLENDFI_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "content-type: application/json" \
  -d '{
    "url": "https://your-app.example.com/blendfi-webhooks",
    "event_types": ["conversion.completed", "conversion.completed"],
    "description": "production handler"
  }'
import crypto from "node:crypto";

const res = await fetch(`${process.env.BLENDFI_BASE}/v1/webhook_endpoints`, {
  method: "POST",
  headers: {
    "authorization": `Bearer ${process.env.BLENDFI_KEY}`,
    "idempotency-key": crypto.randomUUID(),
    "content-type": "application/json",
  },
  body: JSON.stringify({
    url: "https://your-app.example.com/blendfi-webhooks",
    event_types: ["conversion.completed", "conversion.completed"],
    description: "production handler",
  }),
});
const endpoint = await res.json();
console.log("secret (store securely):", endpoint.secret);
import os, uuid, requests

res = requests.post(
    f"{os.environ['BLENDFI_BASE']}/v1/webhook_endpoints",
    headers={
        "authorization": f"Bearer {os.environ['BLENDFI_KEY']}",
        "idempotency-key": str(uuid.uuid4()),
        "content-type": "application/json",
    },
    json={
        "url": "https://your-app.example.com/blendfi-webhooks",
        "event_types": ["conversion.completed", "conversion.completed"],
        "description": "production handler",
    },
)
endpoint = res.json()
print("secret (store securely):", endpoint["secret"])

The response includes a secret, this is the only time the plaintext secret is returned. Store it in your secrets manager immediately. BlendFi keeps a hashed copy for signature verification but cannot return the plaintext again.

{
  "id": "we_01J…",
  "url": "https://your-app.example.com/blendfi-webhooks",
  "event_types": ["conversion.completed", "conversion.completed"],
  "secret": "whsec_…",
  "status": "active",
  "description": "production handler",
  "created_at": "2026-05-04T13:00:00Z"
}

List endpoints

curl $BLENDFI_BASE/v1/webhook_endpoints \
  -H "Authorization: Bearer $BLENDFI_KEY"

Returns paginated endpoints. The plaintext secret is not included on list/get responses.

Update an endpoint

PATCH is partial, send only the fields you want to change.

curl -X PATCH $BLENDFI_BASE/v1/webhook_endpoints/we_01J... \
  -H "Authorization: Bearer $BLENDFI_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "content-type: application/json" \
  -d '{
    "event_types": ["conversion.completed", "conversion.completed", "conversion.failed"],
    "status": "active"
  }'

Common patches:

  • Update event subscriptions. Add or remove from the event_types array.
  • Pause an endpoint. Set status: "disabled" to stop deliveries without losing the endpoint config. Set back to "active" to resume.
  • Change URL. Use this when migrating between environments.

Delete an endpoint

curl -X DELETE $BLENDFI_BASE/v1/webhook_endpoints/we_01J... \
  -H "Authorization: Bearer $BLENDFI_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

Soft-delete; in-flight deliveries continue retrying until exhausted, but no new events are queued.

Rotate the signing secret

Rotation is the right response to: a compromised host, a developer leaving the team, a routine cadence (every 90 days, etc.), or anything that smells off.

curl -X POST $BLENDFI_BASE/v1/webhook_endpoints/we_01J.../rotate_secret \
  -H "Authorization: Bearer $BLENDFI_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

Response:

{
  "id": "we_01J…",
  "secret": "whsec_NEW…",
  "rotated_at": "2026-05-04T14:00:00Z"
}

Cutover plan

Rotation is an immediate cutover: the moment it completes, the old secret stops working and BlendFi signs every subsequent delivery, including retries of earlier events, with the new secret. Deploy the new secret to your verifier promptly. Because a delivery signed with the old secret may already be in flight to your endpoint at the instant you rotate, it is prudent to accept both the old and new secrets for a few seconds during the swap, then drop the old one. Each X-Blendfi-Signature header carries a single t=<unix>,v1=<hex> value, so "accepting both" means trying each secret against that one signature, not parsing multiple signatures from the header.

Errors specific to endpoint management

Full descriptions in the errors catalog:

CodeStatusWhen
invalid_webhook_url400URL not HTTPS, or otherwise malformed
invalid_webhook_event_types400Empty array or contains an unknown event name
max_webhook_endpoints_reached422Organization at the cap; delete an unused endpoint
webhook_endpoint_not_found404ID doesn't exist or out of tenant scope
invalid_webhook_endpoint_state422Operation not allowed in current endpoint state (e.g. patching a deleted endpoint)

On this page