Skip to main content
Documentation
API Reference

Webhooks

Webhook endpoints receive signed referral events. Add, update, rotate and delete endpoints, send a test event, read deliveries, and resend an event.

Webhook endpoints receive a signed event when a referral is claimed, flagged or updated. These routes manage the endpoints and read what was delivered. Receive referral webhooks covers the payloads, the signature check, retries and the limits. The MCP server has the same operations as list_webhook_endpoints, create_webhook_endpoint, update_webhook_endpoint, delete_webhook_endpoint, rotate_webhook_secret, send_test_webhook and list_webhook_deliveries.

Authentication and Permissions

Reading needs an API key with the referrals:read scope. Every change needs referrals:write, and the key's creator must be an owner or admin. The masked signing secret appears in reads only when the creator is an owner or admin. SDK keys are refused with 403 SDK_KEY_ROUTE_FORBIDDEN.

List Endpoints

GET/apps/{id}/webhook-endpoints

List an app's webhook endpoints

Returns the endpoints of one app with the plan's limit per app. Needs the referrals:read scope. The masked secret appears only when the key's creator is an owner or admin.

Parameters

NameTypeInDescription
id*stringpathThe app ID.

Responses

200The app's endpoints
FieldTypeDescription
data*object[]
limit*integerEndpoints per app on the plan: 1 on Free, 5 on paid plans.
plan*string
400INVALID_ID when the ID in the path is not a UUID.
FieldTypeDescription
error*object
401Unauthorized. The key is missing or invalid.
FieldTypeDescription
error*object
403Forbidden. The key needs the referrals:read scope.
FieldTypeDescription
error*object
404The app does not exist in this organization
FieldTypeDescription
error*object

The response includes the plan's endpoint limit per app: 1 on Free and 5 on paid plans.

Add an Endpoint

POST/apps/{id}/webhook-endpoints

Add a webhook endpoint

Adds an endpoint to an app. Needs the referrals:write scope, and the key's creator must be an owner or admin. The full signing secret is in `secret` this once. Later reads show only a masked form. The address must be a public https address: localhost, private networks, addresses with a user name or password, and WarpLink's own addresses are refused.

Parameters

NameTypeInDescription
id*stringpathThe app ID.

Request Body

FieldTypeDescription
url*stringe.g. https://api.example.com/hooks/warplink
send_flaggedbooleanAlso send referral.flagged events.

Responses

201The endpoint, with its signing secret shown once
400VALIDATION_ERROR with fields.url when the address is refused, or INVALID_ID when the app ID is not a UUID.
FieldTypeDescription
error*object
401Unauthorized. The key is missing or invalid.
FieldTypeDescription
error*object
403Forbidden. The key needs the referrals:write scope, and its creator must be an owner or admin.
FieldTypeDescription
error*object
404The app does not exist in this organization
FieldTypeDescription
error*object
409PLAN_LIMIT_EXCEEDED when the app already holds as many endpoints as the plan includes. details.limit is the limit and details.plan the plan. Paused and disabled endpoints count.
FieldTypeDescription
error*object

The address must be a public https address. The full signing secret, which starts with whsec_, is in secret in this response only. Later reads show a masked form.

Update an Endpoint

PATCH/webhook-endpoints/{id}

Update a webhook endpoint

Changes the address, turns the endpoint on or off, or sets referral.flagged delivery. Needs the referrals:write scope, and the key's creator must be an owner or admin. Send at least one field. Only a plan change pauses an endpoint, so status accepts active and disabled. keep_active makes this endpoint the active one and pauses the others the plan no longer covers.

Parameters

NameTypeInDescription
id*stringpathThe endpoint ID.

Request Body

FieldTypeDescription
urlstring
status"active" | "disabled"
send_flaggedboolean
keep_activebooleanCannot be combined with status disabled.

Responses

200The updated endpoint
FieldTypeDescription
id*string
app_id*string
url*stringThe https address WarpLink sends events to.
status*"active" | "disabled" | "paused"active delivers events. disabled was turned off by a person. paused was turned off by a plan change that allows fewer endpoints.
send_flagged*booleanWhether this endpoint also receives referral.flagged events.
secretstringThe masked signing secret. Left out for a key whose creator is not an owner or admin. Create and rotate return the full secret once.
previous_secret_expires_at*string | nullWhile set, the secret from before the last rotation still signs beside the current one.
last_delivery_at*string | null
created_at*string
updated_at*string
400VALIDATION_ERROR for an empty body, a refused address, or keep_active with status disabled. INVALID_ID when the ID is not a UUID.
FieldTypeDescription
error*object
401Unauthorized. The key is missing or invalid.
FieldTypeDescription
error*object
403Forbidden. The key needs the referrals:write scope, and its creator must be an owner or admin.
FieldTypeDescription
error*object
404The endpoint does not exist in this organization
FieldTypeDescription
error*object
409PLAN_LIMIT_EXCEEDED when enabling would pass the plan's limit of active endpoints. Disable another endpoint, or send keep_active.
FieldTypeDescription
error*object

Change the address, turn the endpoint on or off with status, or set send_flagged to false to stop receiving referral.flagged (it is true by default). After a plan change that allows fewer endpoints, keep_active chooses the endpoint that stays active.

Delete an Endpoint

DELETE/webhook-endpoints/{id}

Delete a webhook endpoint

Removes the endpoint with its events and delivery log. Referrals stay recorded. Needs the referrals:write scope, and the key's creator must be an owner or admin.

Parameters

NameTypeInDescription
id*stringpathThe endpoint ID.

Responses

204Deleted
400INVALID_ID when the ID in the path is not a UUID.
FieldTypeDescription
error*object
401Unauthorized. The key is missing or invalid.
FieldTypeDescription
error*object
403Forbidden. The key needs the referrals:write scope, and its creator must be an owner or admin.
FieldTypeDescription
error*object
404The endpoint does not exist in this organization
FieldTypeDescription
error*object

Rotate the Secret

POST/webhook-endpoints/{id}/rotate

Rotate a webhook signing secret

Issues a new signing secret. The full signing secret is in `secret` this once. Later reads show only a masked form. The old secret keeps signing beside the new one until previous_secret_expires_at, 24 hours later, so the receiver can switch without a gap. A second rotation inside that window ends the first old secret at once. Needs the referrals:write scope, and the key's creator must be an owner or admin.

Parameters

NameTypeInDescription
id*stringpathThe endpoint ID.

Responses

200The endpoint, with the new signing secret shown once
400INVALID_ID when the ID in the path is not a UUID.
FieldTypeDescription
error*object
401Unauthorized. The key is missing or invalid.
FieldTypeDescription
error*object
403Forbidden. The key needs the referrals:write scope, and its creator must be an owner or admin.
FieldTypeDescription
error*object
404The endpoint does not exist in this organization
FieldTypeDescription
error*object

The new secret is in secret once. The old one keeps signing beside it until previous_secret_expires_at, 24 hours later, so a receiver can switch without a gap.

Send a Test Event

POST/webhook-endpoints/{id}/test

Send a test event

Sends one signed webhook.test event to the saved address and answers with what the endpoint returned. It is sent once, never retried, and appears in the delivery log. The address is checked again before sending. Needs the referrals:write scope, and the key's creator must be an owner or admin. Takes no body.

Parameters

NameTypeInDescription
id*stringpathThe endpoint ID.

Responses

200The result of the send. A failed send is still a 200 with success false.
FieldTypeDescription
event_id*stringThe id of the webhook.test event, also in the X-WarpLink-Event-Id header.
success*booleanTrue when the endpoint answered with a 2xx status.
outcome*"ok" | "error" | "timeout"
status_code*integer | nullThe status the endpoint answered with, or null when it did not answer.
error*string | null
duration_ms*integer
tested_at*string
400VALIDATION_ERROR when the saved address no longer passes the address check, or INVALID_ID when the ID is not a UUID.
FieldTypeDescription
error*object
401Unauthorized. The key is missing or invalid.
FieldTypeDescription
error*object
403Forbidden. The key needs the referrals:write scope, and its creator must be an owner or admin.
FieldTypeDescription
error*object
404The endpoint does not exist in this organization
FieldTypeDescription
error*object

One signed webhook.test event goes to the saved address, and the response shows what your server answered. It is sent once and never retried.

List Deliveries

GET/webhook-endpoints/{id}/deliveries

List an endpoint's deliveries

Returns the newest 100 events of the endpoint with every attempt, newest first. Needs the referrals:read scope.

Parameters

NameTypeInDescription
id*stringpathThe endpoint ID.

Responses

200The delivery log
FieldTypeDescription
data*object[]
400INVALID_ID when the ID in the path is not a UUID.
FieldTypeDescription
error*object
401Unauthorized. The key is missing or invalid.
FieldTypeDescription
error*object
403Forbidden. The key needs the referrals:read scope.
FieldTypeDescription
error*object
404The endpoint does not exist in this organization
FieldTypeDescription
error*object

The newest 100 events of the endpoint, each with every attempt. A delivery's id is the value to pass to the resend route.

Resend an Event

POST/webhook-events/{id}/resend

Resend a webhook event

Sends a finished event again with the same event id and payload, so the receiver can drop a repeat by id. The event must have finished (delivered or failed) within the last 7 days. Needs the referrals:write scope, and the key's creator must be an owner or admin. Takes no body.

Parameters

NameTypeInDescription
id*stringpathThe delivery ID, the id field of a delivery in the log.

Responses

202The event is queued again
FieldTypeDescription
id*string
event_id*string
status*"pending"
400INVALID_ID when the ID in the path is not a UUID.
FieldTypeDescription
error*object
401Unauthorized. The key is missing or invalid.
FieldTypeDescription
error*object
403Forbidden. The key needs the referrals:write scope, and its creator must be an owner or admin.
FieldTypeDescription
error*object
404The event does not exist in this organization
FieldTypeDescription
error*object
409CONFLICT when the event is still being delivered. Resend it after the last attempt.
FieldTypeDescription
error*object
410GONE when the event finished more than 7 days ago.
FieldTypeDescription
error*object

A delivered or failed event can be sent again for 7 days after its last attempt, with the same event id and payload. An event still in flight answers 409 CONFLICT, and an older one answers 410 GONE.