Graine AI

Get a webhook subscription

Fetch one subscription by id.

Fetch one subscription by id.

This returns the document with that exact id and nothing else — it never substitutes the organisation-wide default for an agent that has no subscription of its own. Use the list endpoint with agent_id to see what actually governs an agent.

Watch secret_unavailable: when it is true the stored secret can no longer be decrypted, deliveries go out unsigned, and your signature check will never pass until you PATCH a fresh secret.

A subscription belonging to another organisation answers 404, exactly as an unknown id does.

Errors: 400, 401, 403, 404, 422, 429, 503.

Rate limit: 1000 requests per minute per organization (bucket default). Exceeding it returns 429 with Retry-After; the X-RateLimit-* response headers report your remaining allowance on every call.

GET
/v2/webhooks/{subscription_id}
/v2/webhooks/b91d2f77-3ea5-4c58-9d10-6f8b4a2c7e31

The Authorization access token

Authorization

Authorization
Required
Bearer <token>

Your Graine API key. Create one in the dashboard under Developers, or via POST /v2/api-keys. Send it as Authorization: Bearer <key>.

In: header

Path Parameters

subscription_id
Required
Subscription Id

The subscription_id returned on create.

Query Parameters

organization_idOrganization Id

Must match the organisation the API key belongs to.

Response Body

200

The subscription. Header values and the secret are never returned.

subscription_id
Required
Subscription Id

Stable id for this subscription.

organization_id
Required
Organization Id

Always the organisation the API key belongs to.

agent_idAgent Id | null

The agent this subscription is scoped to, or null for the organisation-wide default.

scope
Required
Scope

'agent' when agent_id is set, 'organization' for the org-wide default. An agent that has ANY enabled subscription of its own uses only those; the org-wide default is a fallback, not a union.

event_types
Required
Event Types

Resolved event list — never null, never empty.

callback_url
Required
Callback Url

The endpoint we POST to.

method_type
Required
Method Type

POST or PUT.

headers
Required
Headers

Configured header names, values masked as '***'. Values are never returned.

header_names
Required
Header Names

The same header names as a sorted list, for clients that want it flat.

enabled
Required
Enabled

A disabled subscription receives nothing.

has_secret
Required
Has Secret

True when a signing secret is configured.

secretSecret | null

Masked preview ('***') when a secret is set, otherwise null.

secret_unavailable
Required
Secret Unavailable

True when the stored secret can no longer be decrypted. Deliveries go out UNSIGNED while this is true and your signature check will never pass — PATCH a fresh secret to fix it.

created_atCreated At | null

ISO-8601 UTC.

updated_atUpdated At | null

ISO-8601 UTC.

created_byCreated By | null

Who created it.

400

1000 — malformed input the schema could not reject: an unknown event type, a method other than POST/PUT, a reserved header name, or a callback_url pointing at a private, loopback or metadata address.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

401

1100 — missing, unknown or inactive API key. 1101 — a browser session token was presented instead of a gat_ key.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

403

1102 — the key is valid but lacks the scope this endpoint requires, or names another organisation. GET /v2/scopes reports which scopes the key holds.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

404

1200 — no such subscription or delivery in this organisation. Cross-tenant reads answer 404, never 403.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

422

1001 — the body or query failed validation; the message names the first offending field.

error
Required
integer

Stable integer code from the error table. Branch on this, not on the message.

message
Required
string

One human-readable sentence. Wording may change; the code will not.

429

1300 — per-organisation rate limit exceeded. Carries Retry-After.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

503

1501 — the webhook subscription store is unreachable.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

504

1502 — an upstream did not respond in time.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

curl -X GET "https://api.graine.ai/v2/webhooks/b91d2f77-3ea5-4c58-9d10-6f8b4a2c7e31?organization_id=string" \
  -H "Authorization: Bearer <token>"

The subscription. Header values and the secret are never returned.

{
  "subscription_id": "b91d2f77-3ea5-4c58-9d10-6f8b4a2c7e31",
  "organization_id": "string",
  "agent_id": "6c6f4cc3-f56c-479d-8422-7f76694daa29",
  "scope": "agent",
  "event_types": [
    "all_processing_completed"
  ],
  "callback_url": "https://example.com/hooks/graine",
  "method_type": "POST",
  "headers": {
    "Authorization": "***"
  },
  "header_names": [
    "X-Tenant"
  ],
  "enabled": true,
  "has_secret": true,
  "secret": "***",
  "secret_unavailable": false,
  "created_at": "2026-08-20T13:06:01.724Z",
  "updated_at": "2026-08-20T13:27:49.073Z",
  "created_by": "dev_1a2b3c4d5e6f7a8b"
}