Fibric. Docs fibric.io →
Reference preview
!
Reference preview

These docs describe the target Fibric platform contract and proposed developer experience. Public Fibric CLI, API endpoints, and SDK packages are not yet available. All present-tense API, CLI, SDK, tenancy, security, retention, retry, and pricing language below is normative target language, not a statement that the surface is callable or commercially available today. Commands, package names, URLs, responses, limits, and timelines are reference examples unless a page explicitly identifies a deployed BearScope path.

Reference

Webhooks API

This page specifies a proposed webhook contract. No public v1.0 webhook-management service, delivery latency, retry schedule, or retention commitment exists today. The endpoints, signatures, and timelines below are reference examples.

Shared conventions, including authentication, pagination, the Idempotency-Key header, and the error envelope, are defined in the API overview. Error codes are catalogued in Errors.

Subscription event types

An endpoint subscribes to one or more delivery types. Each delivery wraps the full current API object named in the table, so a consumer needs no follow-up fetch for the common cases.

TypeFires whendata contains
plan.proposedAn operator proposes an execution plan.The plan object, verdicts included.
plan.disposedA plan finishes executing, is vetoed, or expires.The plan object in its final state.
action.disposedThe executor disposes one action: allowed, alerted, blocked, or deduplicated.The action object.
action.needs_approvalAn action's verdict is ALERT and a human must approve.The action object, plus its plan_id for the approval call.
connector.status_changedA connector transitions between connected, degraded, error, and pending_auth.The connector object.
receipt.writtenAny receipt is appended, refusals included.The receipt object. High volume; subscribe deliberately.

Types follow the API's noun.verb convention, and new types are additive within the major version; ignore types you do not recognize.

The webhook endpoint object

idstring

Unique identifier, prefixed whk_.

objectstring

Always webhook_endpoint.

urlstring

The HTTPS destination. Plain HTTP is rejected at creation.

typesstring[]

Subscribed delivery types from the table above.

statusstring

active, disabled (by you), or suspended (by Fibric, after sustained delivery failure; see retries).

secretstring

Signing secret, prefixed whsec_. Returned in full at creation and on rotation only; reads return a hint. Used to verify Fibric-Signature.

created_atstring

RFC 3339 timestamp of creation.

last_delivery_atstring or null

Timestamp of the most recent delivery attempt, successful or not.

POST

Create an endpoint

POST/v1/webhook_endpointsscope webhooks:write
urlrequiredstring · body

The HTTPS destination.

typesrequiredstring[] · body

One or more delivery types.

curl
curl -X POST https://api.fibric.io/v1/webhook_endpoints \
  -H "Authorization: Bearer $FIBRIC_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: whk-create-ops-consumer" \
  -d '{
    "url": "https://ops.example.com/fibric/webhook",
    "types": ["plan.proposed", "action.needs_approval", "connector.status_changed"]
  }'
201 Created Response
json
{
  "id": "whk_6b3e0d",
  "object": "webhook_endpoint",
  "url": "https://ops.example.com/fibric/webhook",
  "types": ["plan.proposed", "action.needs_approval", "connector.status_changed"],
  "status": "active",
  "secret": "whsec_5f2e8a1c9b0d7e4f6a3b",
  "created_at": "2026-07-02T15:30:00Z",
  "last_delivery_at": null
}

Error cases:

StatusCodeWhen
400invalid_parameterurl is not HTTPS, or a type is unknown.
409state_conflictAn active endpoint with this url already exists.
GET

List endpoints

GET/v1/webhook_endpointsscope webhooks:read

Returns the tenant's endpoints, newest first, cursor-paginated with the standard limit and cursor parameters. The secret reads as a hint.

PATCH

Update an endpoint

PATCH/v1/webhook_endpoints/{endpoint_id}scope webhooks:write

The target update operation changes endpoint configuration and can rotate a signing secret with a managed overlap window. No public endpoint or standard overlap duration exists today.

curl · rotate the signing secret
curl -X PATCH https://api.fibric.io/v1/webhook_endpoints/whk_6b3e0d \
  -H "Authorization: Bearer $FIBRIC_KEY" \
  -H "Content-Type: application/json" \
  -d '{"rotate_secret": true}'
DELETE

Delete an endpoint

DELETE/v1/webhook_endpoints/{endpoint_id}scope webhooks:write

Deletes the endpoint. Pending retries for it are dropped; delivery records remain readable for their retention window.

The delivery object

Every attempt to reach your endpoint is recorded as a delivery. The same shape is what arrives in the HTTP POST body.

idstring

Unique identifier, prefixed dlv_. Stable across retries of the same delivery: use it as your deduplication key.

objectstring

Always webhook_delivery.

endpoint_idstring

The endpoint this delivery targets.

typestring

The delivery type, for example plan.proposed.

dataobject

The full API object the type names, at the moment the delivery was created.

correlation_idstring

The envelope correlation id threading this delivery to its event, plan, and receipts.

attemptinteger

1-based attempt counter for this delivery.

statusstring

pending, succeeded, or failed (retries exhausted). Read over the API only; the POST body carries the delivery mid-flight.

created_atstring

RFC 3339 timestamp the delivery was created.

json · what arrives at your endpoint
POST /fibric/webhook HTTP/1.1
Content-Type: application/json
Fibric-Signature: t=1782064081,v1=6e8a2c91f0b34d7e5a1c9f82d4b60e3a7c5f9b1d8e2a4c6f0b3d5e7a9c1f4b68

{
  "id": "dlv_9c4f2e",
  "object": "webhook_delivery",
  "endpoint_id": "whk_6b3e0d",
  "type": "action.needs_approval",
  "correlation_id": "co_51d2e8",
  "attempt": 1,
  "created_at": "2026-07-02T15:02:10Z",
  "data": {
    "id": "act_91d1",
    "object": "action",
    "plan_id": "pl_7c1a",
    "tool": "order.notify",
    "entity_key": "order:SO-10884",
    "disposition": "ALERT"
  }
}
GET

List deliveries

GET/v1/webhook_endpoints/{endpoint_id}/deliveriesscope webhooks:read

The proposed endpoint returns cursor-paginated delivery records and illustrates redelivery. Retention is deployment-specific; no public 30-day commitment or callable replay endpoint exists.

Retries and backoff

The table below is a reference retry profile, not a current service commitment. Managed deployments define response deadlines, attempts, backoff, retention, and suspension behavior in writing:

AttemptDelay after previousElapsed (approx.)
1immediate0
230 seconds30 s
32 minutes2.5 m
410 minutes13 m
51 hour1.2 h
66 hours7 h
FinalDeployment-definedDeployment-defined

Jitter, failure state, notification, suspension, and redelivery are target behaviors. They are not a public SLO or retention promise.

i
Deliveries are at-least-once and unordered

Retries and redelivery mean your consumer can see the same dlv_ id twice; deduplicate on it. Ordering across deliveries is not guaranteed, especially under retry. Treat each delivery as a pointer to current state: the data snapshot is convenient, but for decisions, re-read the object by id.

Verifying Fibric-Signature

Every delivery carries a Fibric-Signature header: a Unix timestamp and one or more HMAC-SHA256 signatures, hex-encoded.

the header format
Fibric-Signature: t=1782064081,v1=6e8a2c91f0b34d7e5a1c9f82d4b60e3a7c5f9b1d8e2a4c6f0b3d5e7a9c1f4b68

The signed message is the timestamp, a period, and the raw request body: {t}.{body}. To verify: compute HMAC-SHA256 over that message with your whsec_ secret, compare in constant time against each v1 value (two are present during a secret rotation), and reject if the timestamp is older than your tolerance, five minutes is conventional, to defeat replay.

typescript · verification
import { createHmac, timingSafeEqual } from "node:crypto";

function verifyFibricSignature(header: string, rawBody: string, secret: string): boolean {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // 5-minute tolerance

  const expected = createHmac("sha256", secret)
    .update(`${t}.${rawBody}`)
    .digest("hex");

  const given = Buffer.from(String(parts.v1 ?? ""), "hex");
  const want = Buffer.from(expected, "hex");
  return given.length === want.length && timingSafeEqual(given, want);
}

Verify against the raw body bytes, before any JSON parsing or re-serialization; a re-stringified body will not match. Respond 2xx quickly and do the work asynchronously: the 10-second window includes your processing time.

Errors

StatusCodeWhen
400invalid_parameterA non-HTTPS url, an unknown delivery type, or an invalid status transition.
403insufficient_scopeThe key lacks the webhooks:read or webhooks:write scope the route requires.
404not_foundNo endpoint or delivery with this id exists for the authenticated tenant.
409state_conflictCreating a duplicate url, or redelivering a delivery that is still pending.