---
title: List webhooks
description: List the webhooks that this key can see, oldest first, without their secrets.
doc_version: 0.1.0-preview
last_updated: 2026-09-14
---

# List webhooks

`GET /webhooks`

List the webhooks that this key can see, oldest first, without their secrets.

**Permission:** Cluster key, or a scoped key with read on a namespace or collection that the webhook covers.

[API key types and authentication](/engine/reference/authentication.md).

Lists return items and next_cursor. Keep the same key and filters for the next page. List cursors expire after one hour.

namespace keeps the webhooks whose scope names that namespace, and leaves out cluster webhooks. Add collection to list the webhooks that get that collection’s events, cluster webhooks included.

A namespace or collection key sees only its own namespace and collections in each scope.

## Example request

```http
GET /webhooks HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
```

## Query parameters

### `namespace`

**string · optional · nullable**

Return only webhooks whose scope names this namespace, by name or ID. Without collection, cluster webhooks are left out.

### `collection`

**string · optional · nullable**

Return the webhooks that get this collection’s events, cluster webhooks included. Needs namespace.

### `cursor`

**string · optional · nullable**

Opaque continuation token from next_cursor. Keep the same key, filters, and other request values. Omit it for the first page.

### `limit`

**integer · optional**

Maximum resources in this page. Default 50, minimum 1, maximum 100.

Default: `50`.

- Minimum: 1
- Maximum: 100

## Responses

### 200 · Success

A page of visible webhooks. Secrets are omitted.

Content type: `application/json`.

#### Response headers

##### `x-engine-request-id`

**string · required**

The Engine request ID. Retain it when investigating a failed or unexpected request.

##### `x-request-id`

**string · required**

The X-Request-Id you sent, echoed when it is a valid ID. Otherwise, the Engine request ID.

```json
{
  "items": [
    {
      "id": "whk_01K6Q6N7D8E9F0G1H2J3K4M5N6",
      "name": "acme-status",
      "scope": {
        "kind": "namespace",
        "namespaces": [
          "acme"
        ]
      },
      "url": "https://hooks.acme.example/graphon-events",
      "types": [
        "job.updated",
        "file.status_changed"
      ],
      "enabled": true,
      "disabled_reason": null,
      "signing": {
        "secret_fingerprint": "sha256:9b2d44f0",
        "previous_secret_fingerprint": null,
        "previous_secret_expires_at": null
      },
      "delivery": {
        "pending_deliveries": 0,
        "last_succeeded_at": "2026-10-06T10:05:13Z",
        "last_failed_at": null
      },
      "created_at": "2026-10-06T10:00:00Z",
      "updated_at": "2026-10-06T10:00:00Z"
    }
  ],
  "next_cursor": null
}
```

#### Response fields

##### `items`

**array<object> · required**

Page of webhooks visible to this key. An empty array means no resources matched.

###### `items[].created_at`

**string (date-time) · required**

Time the resource was created, as an ISO 8601 UTC timestamp.

###### `items[].delivery`

**object · required**

Delivery summary: pending events and the times of the last success and failure.

###### `items[].delivery.last_failed_at`

**string (date-time) · required · nullable**

Time of the last attempt that did not succeed. Null before the first one.

###### `items[].delivery.last_succeeded_at`

**string (date-time) · required · nullable**

Time of the last 2xx answer. Null before the first one.

###### `items[].delivery.pending_deliveries`

**integer · required**

Events that are queued or waiting for a retry.

###### `items[].disabled_reason`

**string · required · nullable**

Why the webhook is off: requested (a key set enabled false) or failing (Engine turned it off). Null while it is on.

- `requested`: A key set enabled to false.
- `failing`: Engine turned the webhook off: the receiver answered 410, or sent no 2xx for 72 hours.

###### `items[].enabled`

**boolean · required**

Whether Engine queues and sends events.

###### `items[].id`

**string · required**

Immutable webhook ID with the whk_ prefix.

###### `items[].name`

**string · required**

Webhook name. It never changes. Each POST sends it in X-Graphon-Events-Webhook.

###### `items[].scope`

**object · required**

The webhook’s scope. A namespace or collection key sees only its own namespace and collections in it.

###### cluster

###### `items[].scope.kind`

**"cluster" · required**

Every event in the cluster. Only a cluster key can create or see this webhook.

###### namespace

###### `items[].scope.kind`

**"namespace" · required**

Every event of the listed namespaces, including collections created later and namespace jobs.

###### `items[].scope.namespaces`

**array<string> · required**

Nonempty list of namespace names or IDs. More than one needs a cluster key. A scoped key sees only its own namespace here.

###### collection

###### `items[].scope.collections`

**array<string> · required**

Nonempty list of collection names or IDs in the namespace. The webhook gets their events.

###### `items[].scope.kind`

**"collection" · required**

The events of the named collections in one namespace.

###### `items[].scope.namespace`

**string · required · nullable**

Namespace name or ID that holds the collections. Null in a response when the namespace is being deleted.

###### `items[].secret`

**string · optional · nullable**

The signing secret: whsec_ and the base64 of 32 random bytes. Only the answers to Create and Rotate hold it. Store it before you continue.

###### `items[].signing`

**object · required**

Fingerprints that identify the signing secrets, and the end of a rotation overlap.

###### `items[].signing.previous_secret_expires_at`

**string (date-time) · required · nullable**

When the previous secret stops signing. Null outside a rotation overlap.

###### `items[].signing.previous_secret_fingerprint`

**string · required · nullable**

Fingerprint of the previous secret during a rotation overlap. Otherwise null.

###### `items[].signing.secret_fingerprint`

**string · required**

sha256: and 8 hex characters that identify the current secret without showing it.

###### `items[].types`

**array<string> · required · nullable**

Event types that the webhook gets. Null means every type, also types added later.

###### `items[].updated_at`

**string (date-time) · required**

Time the resource last changed, as an ISO 8601 UTC timestamp.

###### `items[].url`

**string · required**

Receiver URL that Engine POSTs to.

##### `next_cursor`

**string · required · nullable**

Token for the next page, or null when this result has no next page. Do not parse or modify the token.

## Errors

[Error format and retry guidance](/engine/reference/errors.md).

### 400 · `invalid_request`

A field, path, parameter, or conditional request rule is invalid.

Correct the request. Unknown fields are rejected.

```json
{
  "error": {
    "code": "invalid_request",
    "message": "A field, path, parameter, or conditional request rule is invalid.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

### 400 · `invalid_cursor`

The cursor expired or does not belong to this request and key.

Restart from the first page. Preserve the same key, filters, and request values when continuing.

```json
{
  "error": {
    "code": "invalid_cursor",
    "message": "The cursor expired or does not belong to this request and key.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

### 401 · `unauthenticated`

The API key is missing, invalid, or revoked.

Send an active key in Authorization: Bearer or X-API-Key.

```json
{
  "error": {
    "code": "unauthenticated",
    "message": "The API key is missing, invalid, or revoked.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

### 403 · `forbidden`

The key can see the resource but lacks permission for this operation.

Use a key with the required action or scope kind.

```json
{
  "error": {
    "code": "forbidden",
    "message": "The key can see the resource but lacks permission for this operation.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

### 404 · `not_found`

The resource is absent, deleted, or outside this key’s scope.

Check the identifier and the key’s namespace and collection scope.

```json
{
  "error": {
    "code": "not_found",
    "message": "The resource is absent, deleted, or outside this key’s scope.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

### 503 · `temporarily_unavailable`

A dependency, cluster readiness condition, or capacity limit prevents this operation.

Inspect retryable and details. Retry only when permitted, preserving the idempotency key for the same write.

```json
{
  "error": {
    "code": "temporarily_unavailable",
    "message": "A dependency, cluster readiness condition, or capacity limit prevents this operation.",
    "request_id": "req_example",
    "retryable": true,
    "details": {}
  }
}
```

### 500 · `internal_error`

An unexpected server failure prevented this request from completing.

Retain request_id for investigation. Follow retryable before retrying a write.

```json
{
  "error": {
    "code": "internal_error",
    "message": "An unexpected server failure prevented this request from completing.",
    "request_id": "req_example",
    "retryable": false,
    "details": {}
  }
}
```

## Other request languages

### cURL

```bash
curl -sS "$GRAPHON_ENGINE_URL/webhooks" \
  -H "Authorization: Bearer $GRAPHON_ENGINE_API_KEY"
```

### Python

```python
import json
import os
import urllib.request

request = urllib.request.Request(
    os.environ["GRAPHON_ENGINE_URL"] + "/webhooks",
    headers={
        "Authorization": "Bearer " + os.environ["GRAPHON_ENGINE_API_KEY"],
    },
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(response.read().decode())
```

### JavaScript

```javascript
const response = await fetch(process.env.GRAPHON_ENGINE_URL + "/webhooks", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.GRAPHON_ENGINE_API_KEY}`,
  },
});
console.log(response.status, await response.text());
```

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
