Graine AI

Get one webhook delivery

One delivery, with every attempt we made.

One delivery, with every attempt we made.

attempts is the whole story: four entries with HTTP 500 says your endpoint answered and rejected us; four entries with error_class: "dns_error" says we never reached it; one entry and status: "delivered" says it worked first time. response_snippet carries the first part of what your endpoint returned on each attempt.

A row whose status is suppressed has no attempts at all — suppressed_reason says why we never sent it.

A delivery belonging to another organisation answers 404, exactly as an unknown id does: delivery ids are not probeable across tenants. Rows expire after 30 days, so an old id answers 404 too.

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/deliveries/{delivery_id}
/v2/webhooks/deliveries/ca16f23f-a7c6-4e4d-a0b6-446c1e484465

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

delivery_id
Required
Delivery Id

The delivery_id from the deliveries listing.

Query Parameters

organization_idOrganization Id

Must match the organisation the API key belongs to.

Response Body

200

The delivery row with its full attempt history.

delivery_idDelivery Id | null

Stable id for this delivery.

event_idEvent Id | null

Stable per (call, event type) — dedupe on this.

event_typeEvent Type | null

One of the seven event types.

call_idCall Id | null

The execution this event is about.

organization_idOrganization Id | null

Always your own organisation.

agent_idAgent Id | null

The ORIGINAL, pre-A/B-resolution agent id.

subscription_idSubscription Id | null

Which subscription produced this row.

callback_hostCallback Host | null

Only the HOST of the callback URL. The path and query string are withheld because a callback URL routinely carries your own token.

method_typeMethod Type | null

POST or PUT.

signedSigned | null

False means the body went out without an X-Graine-Signature header.

statusStatus | null

pending | delivered | failed | suppressed | unreadable.

attempt_countAttempt Count | null

Attempts made so far (maximum 4).

failure_reasonFailure Reason | null

Why the attempt ladder was exhausted.

suppressed_reasonSuppressed Reason | null

not_subscribed | webhooks_disabled | no_callback_url | url_rejected. Set when no request was made at all.

delivered_atDelivered At | null

ISO-8601 UTC.

failed_atFailed At | null

ISO-8601 UTC.

created_atCreated At | null

ISO-8601 UTC.

attemptsAttempts

Attempt history, oldest first.

body_bytesBody Bytes | null

True size of the body we sent.

body_previewBody Preview | null

First 2000 characters of the body we sent.

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/deliveries/ca16f23f-a7c6-4e4d-a0b6-446c1e484465?organization_id=string" \
  -H "Authorization: Bearer <token>"

The delivery row with its full attempt history.

{
  "delivery_id": "e5b3a1c9-4d72-4f80-b6a3-1c9e7d5f2b48",
  "event_id": "a7f4c1e2-9b3d-5e88-a0c6-3f7d2e9b4c15",
  "event_type": "all_processing_completed",
  "call_id": "dbcffa37-92a1-4ae7-9814-71ca7b8ab3d3",
  "organization_id": "organization-live-EXAMPLE",
  "agent_id": "6c6f4cc3-f56c-479d-8422-7f76694daa29",
  "subscription_id": "b91d2f77-3ea5-4c58-9d10-6f8b4a2c7e31",
  "callback_host": "example.com",
  "method_type": "POST",
  "signed": true,
  "status": "delivered",
  "attempt_count": 1,
  "failure_reason": "http_error",
  "suppressed_reason": "not_subscribed",
  "delivered_at": "2026-08-26T12:25:02.526Z",
  "failed_at": "2026-08-26T12:25:14.902Z",
  "created_at": "2026-08-26T12:25:01.998Z",
  "attempts": [
    {
      "attempt": 1,
      "started_at": "2026-08-26T12:25:02.114Z",
      "duration_ms": 412,
      "http_status": 200,
      "error_class": "timeout",
      "error_message": "Read timed out after 10s.",
      "response_snippet": "{\"received\": true}"
    }
  ],
  "body_bytes": 4821,
  "body_preview": "{\"event_type\": \"all_processing_completed\", \"call_id\": \"dbcffa37-92a1-4ae7-9814-71ca7b8ab3d3\"}"
}