Documentation
DocsAPI reference

Webhook endpoints

A webhook endpoint is a URL on a service of yours that a pipeline's webhook block can ask for an outcome.

Updated Sep 15, 2026

A webhook block posts the request to its endpoint, and the endpoint answers with next, human, approve, or deny. Deliveries are signed with the endpoint's secret, returned once when its first revision is created. Verify the WithHuman-Signature header with it.

To change an endpoint, create a revision, test it, then activate it. URLs must be public HTTPS.

List webhook endpoints

GET/api/v1/webhook_endpointsSession or API keyRequires webhook.read

Returns every webhook endpoint in the organization, one entry per key. Each entry carries the latest revision's name and URL, the active revision number, and the active pipeline revisions that post to it. Signing secrets are never included.

Request

Parameters

ParameterTypeDescription
limitquery · integer

How many endpoints to return. Defaults to 200.

Response

Response codes

StatusBodyDescription
200object

The endpoints

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot read webhook endpoints

501ErrorResponse

This deployment has no secrets key, so webhook endpoints are unavailable

Response body200

Example

GET /api/v1/webhook_endpoints
curl -X GET "$WITHHUMAN_URL/api/v1/webhook_endpoints" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "webhook_endpoints": [
    {
      "endpoint_key": "string",
      "name": "string",
      "url": "https://example.com/webhooks/withhuman",
      "active_revision": 1,
      "archived_at": "2026-09-08T12:02:11Z",
      "latest_revision": 1,
      "revision_count": 1,
      "latest_created_at": "2026-09-08T12:02:11Z",
      "secret_rotated_at": "2026-09-08T12:02:11Z",
      "uses": [
        {
          "pipeline_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
          "scope": "organization",
          "agent_slug": "string",
          "revision": 1,
          "block_key": "string"
        }
      ]
    }
  ]
}

Retrieve a webhook endpoint

GET/api/v1/webhook_endpoints/{endpoint_key}Session or API keyRequires webhook.read

Returns the endpoint's active revision. This is where deliveries go right now.

The ETag header carries the active revision number. Pass it as If-Match when you activate another revision or archive the endpoint.

Request

Parameters

ParameterTypeDescription
endpoint_keyrequiredpath · string

The endpoint's key. Lowercase letters, digits, dots, underscores and hyphens, up to 63 characters. You choose it when you create the first revision.

Response

Response codes

StatusBodyDescription
200WebhookEndpointRevision

The active revision

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot read webhook endpoints

404ErrorResponse

No such endpoint, or no revision is active

Response body200

iduuidrequired
endpoint_keystringrequired
revisionint64required

The revision number. Revisions count up from 1.

is_activebooleanrequired

Whether deliveries go to this revision.

namestringrequired

The display name.

urlurirequired

Where deliveries go.

The membership or organization-key actor that created the revision.

created_atdate-timerequired

Present only in the response that created the endpoint's first revision. Starts with whsec_. Your receiver uses it to verify the WithHuman-Signature header.

Example

GET /api/v1/webhook_endpoints/{endpoint_key}
curl -X GET "$WITHHUMAN_URL/api/v1/webhook_endpoints/{endpoint_key}" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "endpoint_key": "string",
  "revision": 1,
  "is_active": true,
  "name": "Fraud check",
  "url": "https://fraud.example.com/approvals",
  "created_by_actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "created_at": "2026-09-08T12:02:11Z",
  "signing_secret": "whsec_9f2c1b7e4d3a4f8b"
}

List webhook endpoint revisions

GET/api/v1/webhook_endpoints/{endpoint_key}/revisionsSession or API keyRequires webhook.read

Returns the endpoint's revisions, newest first. Signing secrets are never included.

Paging is by cursor. When more revisions follow, the response carries next_cursor. Pass it back as cursor to get the next page. The last page has no next_cursor. total_count is how many revisions there are across every page.

Request

Parameters

ParameterTypeDescription
endpoint_keyrequiredpath · string

The endpoint's key. Lowercase letters, digits, dots, underscores and hyphens, up to 63 characters. You choose it when you create the first revision.

cursorquery · string

The next_cursor from the previous page.

limitquery · integer

How many revisions to return per page. Defaults to 50.

Response

Response codes

StatusBodyDescription
200object

The revisions, newest first

400ErrorResponse

cursor is not a cursor this endpoint issued

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot read webhook endpoints

Response body200

The revisions on this page, newest first.

Present when another page follows.

total_countint64required

How many revisions the endpoint has, across every page.

Example

GET /api/v1/webhook_endpoints/{endpoint_key}/revisions
curl -X GET "$WITHHUMAN_URL/api/v1/webhook_endpoints/{endpoint_key}/revisions" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "revisions": [
    {
      "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
      "endpoint_key": "string",
      "revision": 1,
      "is_active": true,
      "name": "Fraud check",
      "url": "https://fraud.example.com/approvals",
      "created_by_actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
      "created_at": "2026-09-08T12:02:11Z",
      "signing_secret": "whsec_9f2c1b7e4d3a4f8b"
    }
  ],
  "next_cursor": "string",
  "total_count": 1
}

Create a webhook endpoint revision

POST/api/v1/webhook_endpoints/{endpoint_key}/revisionsSession or API keyRequires webhook.write

Creates a new revision of an endpoint from a name and a URL. If the key is new, this creates the endpoint and its signing secret. The secret is returned once, in this response, as signing_secret. Store it where your receiver can read it. It cannot be retrieved again.

Later revisions change the name or the URL only. The secret stays the same, so your receiver keeps working. The URL must be a public HTTPS address and is checked against the egress policy before the revision is created. The revision is created inactive. Activate it to put it into use.

Request

Parameters

ParameterTypeDescription
endpoint_keyrequiredpath · string

The endpoint's key. Lowercase letters, digits, dots, underscores and hyphens, up to 63 characters. You choose it when you create the first revision.

Request body

namestringrequired

A display name. Pipeline authors see it when they pick an endpoint.

urlurirequired

An absolute public HTTPS URL. It is checked against the egress policy, which refuses private and internal addresses.

Response

Response codes

StatusBodyDescription
201WebhookEndpointRevision

The new revision, inactive. signing_secret is present only for the endpoint's first revision

400ErrorResponse

The name is empty, or the URL fails the egress policy

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot edit webhook endpoints

501ErrorResponse

This deployment has no secrets key, so webhook endpoints are unavailable

Response body201

iduuidrequired
endpoint_keystringrequired
revisionint64required

The revision number. Revisions count up from 1.

is_activebooleanrequired

Whether deliveries go to this revision.

namestringrequired

The display name.

urlurirequired

Where deliveries go.

The membership or organization-key actor that created the revision.

created_atdate-timerequired

Present only in the response that created the endpoint's first revision. Starts with whsec_. Your receiver uses it to verify the WithHuman-Signature header.

Example

POST /api/v1/webhook_endpoints/{endpoint_key}/revisions
curl -X POST "$WITHHUMAN_URL/api/v1/webhook_endpoints/{endpoint_key}/revisions" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Fraud check",
  "url": "https://fraud.example.com/approvals"
}'
201 response
{
  "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "endpoint_key": "string",
  "revision": 1,
  "is_active": true,
  "name": "Fraud check",
  "url": "https://fraud.example.com/approvals",
  "created_by_actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "created_at": "2026-09-08T12:02:11Z",
  "signing_secret": "whsec_9f2c1b7e4d3a4f8b"
}

Retrieve a webhook endpoint revision

GET/api/v1/webhook_endpoints/{endpoint_key}/revisions/{revision}Session or API keyRequires webhook.read

Returns one revision of an endpoint, active or not. The signing secret is never included.

Request

Parameters

ParameterTypeDescription
endpoint_keyrequiredpath · string

The endpoint's key. Lowercase letters, digits, dots, underscores and hyphens, up to 63 characters. You choose it when you create the first revision.

revisionrequiredpath · int64

The revision number. Revisions count up from 1.

Response

Response codes

StatusBodyDescription
200WebhookEndpointRevision

The revision

400ErrorResponse

revision is not a positive integer

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot read webhook endpoints

404ErrorResponse

No such revision

Response body200

iduuidrequired
endpoint_keystringrequired
revisionint64required

The revision number. Revisions count up from 1.

is_activebooleanrequired

Whether deliveries go to this revision.

namestringrequired

The display name.

urlurirequired

Where deliveries go.

The membership or organization-key actor that created the revision.

created_atdate-timerequired

Present only in the response that created the endpoint's first revision. Starts with whsec_. Your receiver uses it to verify the WithHuman-Signature header.

Example

GET /api/v1/webhook_endpoints/{endpoint_key}/revisions/{revision}
curl -X GET "$WITHHUMAN_URL/api/v1/webhook_endpoints/{endpoint_key}/revisions/{revision}" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "endpoint_key": "string",
  "revision": 1,
  "is_active": true,
  "name": "Fraud check",
  "url": "https://fraud.example.com/approvals",
  "created_by_actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "created_at": "2026-09-08T12:02:11Z",
  "signing_secret": "whsec_9f2c1b7e4d3a4f8b"
}

Activate a webhook endpoint revision

POST/api/v1/webhook_endpoints/{endpoint_key}/revisions/{revision}/activateSession or API keyRequires webhook.write

Makes a revision the active one. Deliveries go to its URL from the next request on. A request that is paused on a webhook block and resumes later delivers to whichever revision is active at that moment. Activating an older revision is how you roll back.

Pass the revision you expect to be active in If-Match, quoted, as returned in ETag. Pass "0" if no revision is active. If the active revision changed in the meantime, the call fails with 412 and nothing changes.

Request

Parameters

ParameterTypeDescription
endpoint_keyrequiredpath · string

The endpoint's key. Lowercase letters, digits, dots, underscores and hyphens, up to 63 characters. You choose it when you create the first revision.

revisionrequiredpath · int64

The revision number. Revisions count up from 1.

If-Matchrequiredheader · string

The revision you expect to be active, quoted, for example "2". Take it from the ETag of your last read. If the active revision changed in the meantime, the call fails with 412 and nothing changes. Escalation paths and webhook endpoints accept "0" when no revision is active. Pipelines always have an active revision.

Response

Response codes

StatusBodyDescription
200WebhookEndpointRevision

The revision, now active

400ErrorResponse

revision or If-Match is malformed

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot edit webhook endpoints

404ErrorResponse

No such revision

412ErrorResponse

If-Match does not match the active revision

428ErrorResponse

The If-Match header is missing

501ErrorResponse

This deployment has no secrets key, so webhook endpoints are unavailable

Response body200

iduuidrequired
endpoint_keystringrequired
revisionint64required

The revision number. Revisions count up from 1.

is_activebooleanrequired

Whether deliveries go to this revision.

namestringrequired

The display name.

urlurirequired

Where deliveries go.

The membership or organization-key actor that created the revision.

created_atdate-timerequired

Present only in the response that created the endpoint's first revision. Starts with whsec_. Your receiver uses it to verify the WithHuman-Signature header.

Example

POST /api/v1/webhook_endpoints/{endpoint_key}/revisions/{revision}/activate
curl -X POST "$WITHHUMAN_URL/api/v1/webhook_endpoints/{endpoint_key}/revisions/{revision}/activate" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY" \
  -H "If-Match: "2""
200 response
{
  "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "endpoint_key": "string",
  "revision": 1,
  "is_active": true,
  "name": "Fraud check",
  "url": "https://fraud.example.com/approvals",
  "created_by_actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "created_at": "2026-09-08T12:02:11Z",
  "signing_secret": "whsec_9f2c1b7e4d3a4f8b"
}

Test a webhook endpoint revision

POST/api/v1/webhook_endpoints/{endpoint_key}/revisions/{revision}/testSession or API keyRequires webhook.write

Sends one signed test delivery to the revision's URL and reports what came back. The payload has type webhook_endpoint.test and is flagged as a preview, so your receiver can tell it from a real request. It is signed with the endpoint's secret, so the test also checks your signature verification. The call waits up to 10 seconds for an answer.

You can test a revision before activating it. Each test is recorded in the audit log.

Request

Parameters

ParameterTypeDescription
endpoint_keyrequiredpath · string

The endpoint's key. Lowercase letters, digits, dots, underscores and hyphens, up to 63 characters. You choose it when you create the first revision.

revisionrequiredpath · int64

The revision number. Revisions count up from 1.

Response

Response codes

StatusBodyDescription
200object

What the endpoint answered

400ErrorResponse

revision is not a positive integer

403ErrorResponse

You cannot edit webhook endpoints

404ErrorResponse

No such revision

501ErrorResponse

This deployment has no secrets key, so webhook endpoints are unavailable

Response body200

What one test delivery produced. problem is absent when the endpoint answered with a valid outcome.

Example

POST /api/v1/webhook_endpoints/{endpoint_key}/revisions/{revision}/test
curl -X POST "$WITHHUMAN_URL/api/v1/webhook_endpoints/{endpoint_key}/revisions/{revision}/test" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "test": {
    "status_code": 1,
    "duration_ms": 1,
    "outcome": "next",
    "reason": "string",
    "problem": "blocked",
    "message": "string"
  }
}

List where a webhook endpoint is used

GET/api/v1/webhook_endpoints/{endpoint_key}/usesSession or API keyRequires webhook.read

Returns the active pipeline revisions that post to this endpoint, one entry per webhook block. While this list is not empty, the endpoint cannot be archived.

Request

Parameters

ParameterTypeDescription
endpoint_keyrequiredpath · string

The endpoint's key. Lowercase letters, digits, dots, underscores and hyphens, up to 63 characters. You choose it when you create the first revision.

Response

Response codes

StatusBodyDescription
200object

The active uses. Empty when the endpoint can be archived

400ErrorResponse

endpoint_key is malformed

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot read webhook endpoints

Response body200

usesarray<PipelineUse>required

Example

GET /api/v1/webhook_endpoints/{endpoint_key}/uses
curl -X GET "$WITHHUMAN_URL/api/v1/webhook_endpoints/{endpoint_key}/uses" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "uses": [
    {
      "pipeline_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
      "scope": "organization",
      "agent_slug": "string",
      "revision": 1,
      "block_key": "string"
    }
  ]
}

Archive a webhook endpoint

DELETE/api/v1/webhook_endpoints/{endpoint_key}/activeSession or API keyRequires webhook.write

Deactivates the endpoint's current revision, so the endpoint has no active revision. Its history and its signing secret are kept, and you can activate a revision again later.

Archiving is refused while an active pipeline revision posts to the endpoint. Activate pipeline revisions without that block first. While the endpoint is archived, no pipeline revision that posts to it can be activated. A request that resumes onto it goes to a person, with the block error endpoint_unavailable.

Pass the active revision in If-Match, quoted, as returned in ETag.

Request

Parameters

ParameterTypeDescription
endpoint_keyrequiredpath · string

The endpoint's key. Lowercase letters, digits, dots, underscores and hyphens, up to 63 characters. You choose it when you create the first revision.

If-Matchrequiredheader · string

The revision you expect to be active, quoted, for example "2". Take it from the ETag of your last read. If the active revision changed in the meantime, the call fails with 412 and nothing changes. Escalation paths and webhook endpoints accept "0" when no revision is active. Pipelines always have an active revision.

Response

Response codes

StatusBodyDescription
204

The endpoint is archived

400ErrorResponse

If-Match is malformed or "0"

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot edit webhook endpoints

409ErrorResponse

An active pipeline revision posts to this endpoint. error.code is webhook_endpoint_in_use, and error.details.uses lists the revisions

412ErrorResponse

If-Match does not match the active revision

428ErrorResponse

The If-Match header is missing

Example

DELETE /api/v1/webhook_endpoints/{endpoint_key}/active
curl -X DELETE "$WITHHUMAN_URL/api/v1/webhook_endpoints/{endpoint_key}/active" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY" \
  -H "If-Match: "2""

Rotate the signing secret

POST/api/v1/webhook_endpoints/{endpoint_key}/rotate_secretSession or API keyRequires webhook.write

Replaces the endpoint's signing secret with a new one. The old secret stops working at once, for every revision of the endpoint. The new secret is returned once, in this response. Update your receiver right away, or its signature checks will fail. Each rotation is recorded in the audit log.

Request

Parameters

ParameterTypeDescription
endpoint_keyrequiredpath · string

The endpoint's key. Lowercase letters, digits, dots, underscores and hyphens, up to 63 characters. You choose it when you create the first revision.

Response

Response codes

StatusBodyDescription
200WebhookEndpointSecret

The new secret. It appears only in this response

403ErrorResponse

You cannot edit webhook endpoints

404ErrorResponse

No such endpoint

501ErrorResponse

This deployment has no secrets key, so webhook endpoints are unavailable

Response body200

endpoint_keystringrequired
signing_secretstringrequired

The new secret. It appears only in this response. Starts with whsec_. Your receiver uses it to verify the WithHuman-Signature header.

secret_rotated_atdate-timerequired

When the secret was rotated.

Example

POST /api/v1/webhook_endpoints/{endpoint_key}/rotate_secret
curl -X POST "$WITHHUMAN_URL/api/v1/webhook_endpoints/{endpoint_key}/rotate_secret" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "endpoint_key": "string",
  "signing_secret": "whsec_9f2c1b7e4d3a4f8b",
  "secret_rotated_at": "2026-09-08T12:02:11Z"
}