API reference

Webhook endpoints

A webhook endpoint is a URL of yours that receives Gemlead's events as they happen. You can have 10 per account. Read Webhooks for the events, their payloads and how to verify a signature.

The webhook endpoint object

A URL of yours that Gemlead sends events to. See Webhooks for the events and how to verify them.

Attributes

  • idstring
    Unique identifier for the endpoint.
  • objectstring
    Always webhook_endpoint.
  • urlstring
    The HTTPS URL events are sent to.
  • descriptionstring or null
    Your note about the endpoint.
  • eventsarray of strings
    The event types sent to it.
    lead.createdlead.hotreply.receivedreaction.receivedsam.suggestion.readysam.reply.sentsam.handoff
  • statusstring
    Whether events are sent to it.
    enableddisabled
  • filtersobject
    Which events it gets, by the lead's persona. They apply to every event type.
  • disabled_reasonstring or null
    Why it is disabled. manual when you turned it off, failing when Gemlead did after 3 days of failures in a row and at least 8 failed attempts. null while enabled.
    manualfailing
  • secretstring
    The signing secret, whsec_ and 32 characters. Only in the responses of create and roll secret.
  • created_atstring
    When the endpoint was created, ISO 8601.
  • updated_atstring
    When the endpoint last changed, ISO 8601.
Webhook endpoint object
{
  "id": "wh3LpX9dKe",
  "object": "webhook_endpoint",
  "url": "https://example.com/webhooks/gemlead",
  "description": "CRM sync",
  "events": ["lead.hot", "reply.received"],
  "status": "enabled",
  "filters": {
    "persona_ids": ["lvWBPnytpS"]
  },
  "disabled_reason": null,
  "created_at": "2026-09-14T09:21:05.300Z",
  "updated_at": "2026-11-06T07:45:12.904Z"
}

List webhook endpoints

GET/v1/webhook_endpointsread scope

Returns your webhook endpoints, without their secrets.

Query parameters

  • limitinteger
    How many objects to return, from 1 to 100. Defaults to 25.
  • cursorstring
    The next_cursor of the previous page, to get the page after it. See Pagination.

Returns

A list of webhook endpoint objects.

GET/v1/webhook_endpoints
curl https://gemlead.ai/api/v1/webhook_endpoints \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "object": "list",
  "data": [
    {
      "id": "wh3LpX9dKe",
      "object": "webhook_endpoint",
      "url": "https://example.com/webhooks/gemlead",
      "description": "CRM sync",
      "events": ["lead.hot", "reply.received"],
      "status": "enabled",
      "filters": {
        "persona_ids": ["lvWBPnytpS"]
      },
      "disabled_reason": null,
      "created_at": "2026-09-14T09:21:05.300Z",
      "updated_at": "2026-11-06T07:45:12.904Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Create a webhook endpoint

POST/v1/webhook_endpointswrite scope

Registers a URL for one or more event types. Store the secret of the response, it is the only time you see it.

Body parameters

  • urlstringRequired
    An HTTPS URL that answers on the public internet.
  • eventsarray of stringsRequired
    The event types to send.
    lead.createdlead.hotreply.receivedreaction.receivedsam.suggestion.readysam.reply.sentsam.handoff
  • descriptionstring
    A note for yourself.
  • filtersobject
    Which events to send, by the lead's persona.

Returns

The new webhook endpoint object with its secret.

Errors

POST/v1/webhook_endpoints
curl -X POST https://gemlead.ai/api/v1/webhook_endpoints \
  -H "Authorization: Bearer $GEMLEAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks/gemlead",
    "events": ["lead.hot", "reply.received"],
    "description": "CRM sync",
    "filters": {
      "persona_ids": ["lvWBPnytpS"]
    }
  }'
Response200
{
  "id": "wh3LpX9dKe",
  "object": "webhook_endpoint",
  "url": "https://example.com/webhooks/gemlead",
  "description": "CRM sync",
  "events": ["lead.hot", "reply.received"],
  "status": "enabled",
  "filters": {
    "persona_ids": ["lvWBPnytpS"]
  },
  "disabled_reason": null,
  "created_at": "2026-09-14T09:21:05.300Z",
  "updated_at": "2026-11-06T07:45:12.904Z",
  "secret": "whsec_4QeX7nP2kR9tLm3Vb8YzC1dF6hJ0sWuA"
}

Retrieve a webhook endpoint

GET/v1/webhook_endpoints/:idread scope

Returns one webhook endpoint, without its secret.

Path parameters

  • idstringRequired
    The webhook endpoint's ID.

Returns

A webhook endpoint object.

Errors

GET/v1/webhook_endpoints/:id
curl https://gemlead.ai/api/v1/webhook_endpoints/wh3LpX9dKe \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "id": "wh3LpX9dKe",
  "object": "webhook_endpoint",
  "url": "https://example.com/webhooks/gemlead",
  "description": "CRM sync",
  "events": ["lead.hot", "reply.received"],
  "status": "enabled",
  "filters": {
    "persona_ids": ["lvWBPnytpS"]
  },
  "disabled_reason": null,
  "created_at": "2026-09-14T09:21:05.300Z",
  "updated_at": "2026-11-06T07:45:12.904Z"
}

Update a webhook endpoint

PATCH/v1/webhook_endpoints/:idwrite scope

Changes an endpoint. Set status to enabled to turn back on an endpoint Gemlead disabled. Turning it on or giving it a new url starts its failure count again.

Path parameters

  • idstringRequired
    The webhook endpoint's ID.

Body parameters

  • urlstring
    A new HTTPS URL.
  • eventsarray of strings
    The event types to send.
    lead.createdlead.hotreply.receivedreaction.receivedsam.suggestion.readysam.reply.sentsam.handoff
  • descriptionstring
    A note for yourself.
  • statusstring
    Turn the endpoint on or off.
    enableddisabled
  • filtersobject
    Which events to send, by the lead's persona.

Returns

The updated webhook endpoint object.

Errors

  • No webhook endpoint with this ID on the key's account.
  • A parameter has a value the API does not accept. param names it.
  • The body has a field this endpoint does not take.
  • The URL is not HTTPS, has credentials in it, or points to a private address.
PATCH/v1/webhook_endpoints/:id
curl -X PATCH \
  https://gemlead.ai/api/v1/webhook_endpoints/wh3LpX9dKe \
  -H "Authorization: Bearer $GEMLEAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "enabled"
  }'
Response200
{
  "id": "wh3LpX9dKe",
  "object": "webhook_endpoint",
  "url": "https://example.com/webhooks/gemlead",
  "description": "CRM sync",
  "events": ["lead.hot", "reply.received"],
  "status": "enabled",
  "filters": {
    "persona_ids": ["lvWBPnytpS"]
  },
  "disabled_reason": null,
  "created_at": "2026-09-14T09:21:05.300Z",
  "updated_at": "2026-11-06T07:45:12.904Z"
}

Delete a webhook endpoint

DELETE/v1/webhook_endpoints/:idwrite scope

Deletes an endpoint. Deliveries still waiting for a retry are dropped.

Path parameters

  • idstringRequired
    The webhook endpoint's ID.

Returns

An object with the endpoint's id and deleted set to true.

Errors

DELETE/v1/webhook_endpoints/:id
curl -X DELETE \
  https://gemlead.ai/api/v1/webhook_endpoints/wh3LpX9dKe \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "id": "wh3LpX9dKe",
  "object": "webhook_endpoint",
  "deleted": true
}

Roll the signing secret

POST/v1/webhook_endpoints/:id/roll_secretwrite scope

Replaces the endpoint's secret at once, the old one stops working. Deliveries that fail meanwhile are retried, signed with the new secret.

Path parameters

  • idstringRequired
    The webhook endpoint's ID.

Returns

The webhook endpoint object with its new secret.

Errors

POST/v1/webhook_endpoints/:id/roll_secret
curl -X POST \
  https://gemlead.ai/api/v1/webhook_endpoints/wh3LpX9dKe/roll_secret \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "id": "wh3LpX9dKe",
  "object": "webhook_endpoint",
  "url": "https://example.com/webhooks/gemlead",
  "description": "CRM sync",
  "events": ["lead.hot", "reply.received"],
  "status": "enabled",
  "filters": {
    "persona_ids": ["lvWBPnytpS"]
  },
  "disabled_reason": null,
  "created_at": "2026-09-14T09:21:05.300Z",
  "updated_at": "2026-11-06T07:45:12.904Z",
  "secret": "whsec_4QeX7nP2kR9tLm3Vb8YzC1dF6hJ0sWuA"
}

Send a test event

POST/v1/webhook_endpoints/:id/testwrite scope

Sends a sample event of the endpoint's first event type, with data.test set to true and IDs starting with test_. One attempt, no retry.

Path parameters

  • idstringRequired
    The webhook endpoint's ID.

Returns

A webhook delivery object with the status and status_code your endpoint answered.

Errors

POST/v1/webhook_endpoints/:id/test
curl -X POST \
  https://gemlead.ai/api/v1/webhook_endpoints/wh3LpX9dKe/test \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "id": "dL5qW1zXa8",
  "object": "webhook_delivery",
  "endpoint_id": "wh3LpX9dKe",
  "event_id": "evt_8kQ2vXr4LmT9wPz1Hc6YbN3d",
  "event_type": "lead.hot",
  "status": "succeeded",
  "attempts": 1,
  "status_code": 200,
  "error": null,
  "test": true,
  "next_attempt_at": null,
  "last_attempt_at": "2026-11-06T07:45:12.904Z",
  "created_at": "2026-11-06T07:45:12.904Z"
}

The webhook delivery object

One event sent to one endpoint, with its attempts and your server's last answer.

Attributes

  • idstring
    Unique identifier for the delivery.
  • objectstring
    Always webhook_delivery.
  • endpoint_idstring
    The endpoint it was sent to.
  • event_idstring
    The event sent, the id your server received.
  • event_typestring
    The event's type.
    lead.createdlead.hotreply.receivedreaction.receivedsam.suggestion.readysam.reply.sentsam.handoff
  • statusstring
    pending while attempts are left, then succeeded or failed.
    pendingsucceededfailed
  • attemptsinteger
    Attempts made so far, 8 at most.
  • status_codeinteger or null
    The HTTP status of your last answer. null when there was none, after a timeout or a connection error.
  • errorstring or null
    What went wrong on the last attempt, like the status and the start of your answer, or a timeout.
  • testboolean
    true for a test event.
  • next_attempt_atstring or null
    When the next attempt is due, while pending.
  • last_attempt_atstring or null
    When the last attempt was made.
  • created_atstring
    When the delivery was created, ISO 8601.
Webhook delivery object
{
  "id": "dR7mK2pVn4",
  "object": "webhook_delivery",
  "endpoint_id": "wh3LpX9dKe",
  "event_id": "evt_3Hn7QpW2xZk9LmR4tV8bYc1D",
  "event_type": "reply.received",
  "status": "pending",
  "attempts": 2,
  "status_code": 503,
  "error": "HTTP 503: Service Unavailable",
  "test": false,
  "next_attempt_at": "2026-11-06T08:18:10.000Z",
  "last_attempt_at": "2026-11-06T08:13:10.000Z",
  "created_at": "2026-11-06T08:12:10.000Z"
}

List deliveries

GET/v1/webhook_endpoints/:id/deliveriesread scope

Returns the endpoint's latest deliveries, newest first, test events included. Deliveries are kept 30 days.

Path parameters

  • idstringRequired
    The webhook endpoint's ID.

Query parameters

  • limitinteger
    How many deliveries to return, from 1 to 100. 25 by default.

Returns

A list of webhook delivery objects. This list has no next_cursor, raise limit to see more.

Errors

GET/v1/webhook_endpoints/:id/deliveries
curl -G \
  https://gemlead.ai/api/v1/webhook_endpoints/wh3LpX9dKe/deliveries \
  -H "Authorization: Bearer $GEMLEAD_API_KEY" \
  -d limit=10
Response200
{
  "object": "list",
  "data": [
    {
      "id": "dR7mK2pVn4",
      "object": "webhook_delivery",
      "endpoint_id": "wh3LpX9dKe",
      "event_id": "evt_3Hn7QpW2xZk9LmR4tV8bYc1D",
      "event_type": "reply.received",
      "status": "pending",
      "attempts": 2,
      "status_code": 503,
      "error": "HTTP 503: Service Unavailable",
      "test": false,
      "next_attempt_at": "2026-11-06T08:18:10.000Z",
      "last_attempt_at": "2026-11-06T08:13:10.000Z",
      "created_at": "2026-11-06T08:12:10.000Z"
    },
    {
      "id": "dL5qW1zXa8",
      "object": "webhook_delivery",
      "endpoint_id": "wh3LpX9dKe",
      "event_id": "evt_8kQ2vXr4LmT9wPz1Hc6YbN3d",
      "event_type": "lead.hot",
      "status": "succeeded",
      "attempts": 1,
      "status_code": 200,
      "error": null,
      "test": true,
      "next_attempt_at": null,
      "last_attempt_at": "2026-11-06T07:45:12.904Z",
      "created_at": "2026-11-06T07:45:12.904Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}