> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentova.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# List webhook subscriptions

> Lists all the webhook subscriptions of the workspace, whichever API key created them, including disabled ones (`disabled_at` set) until they are deleted automatically, 30 days after being disabled. Not paginated. The full `url` is returned only for the subscriptions created with the calling API key; for the others, `url` is reduced to its origin (for example `https://hooks.zapier.com`), since the path of a hook URL carries the connector's secret token.




## OpenAPI

````yaml /openapi/openapi-v1.yaml get /webhooks
openapi: 3.0.3
info:
  title: Agentova Public API
  version: 1.0.0
  termsOfService: https://agentova.ai/legal/terms-of-use
  license:
    name: Proprietary — Agentova terms of use
    url: https://agentova.ai/legal/terms-of-use
  contact:
    name: Agentova support
    email: contact@agentova.ai
    url: https://docs.agentova.ai
  description: >
    The Agentova Public API lets your own code, Zapier or n8n work with an

    Agentova workspace: read its automations, runs and leads, pause and resume

    its automations, and receive events through signed webhooks.



    ## Base URL and authentication


    All endpoints are served over HTTPS under `https://core-api.agentova.ai/v1`.

    Every request carries an API key, created in the Agentova app

    (Settings → API), in the `Authorization` header:

    `Authorization: Bearer agk_live_…`


    - A key belongs to one workspace and gives access to the whole workspace.
      The key identifies the workspace: no workspace identifier is ever sent.
    - Every key starts with `agk_live_`. There are no test keys and no separate
      test environment: to experiment safely, use a dedicated workspace.
    - A revoked key is refused immediately, on every endpoint.

    - The API is meant to be called from a server. It sends no CORS headers,
      so a web page cannot call it from a browser, and an `OPTIONS` request
      receives an error in the format described under Errors.


    ## Stability


    This is version 1.0.0 of the v1 API, and v1 is stable: no breaking change

    will be made under `/v1`. Additive changes can still happen: new optional

    fields, new event types, new enum values. Your client must ignore the

    fields, event types and enum values it does not know.



    ## Coverage


    - **Automations**: the messaging automations of the workspace on Meta
      networks (`facebook`, `instagram`, `instagram_page`), WhatsApp
      (`whatsapp`) and e-mail (`gmail`, `microsoft_outlook`, `imap`), with the
      types `social_comments`, `social_story`, `social_messages`, `lead_ads`
      and `email_messages`, plus the CRM sources (`crm_source`). They can all
      be read, and paused or resumed with `PATCH`.
    - **Leads**: from the sources `widget`, `lead_ads`, `telephony`, `social`
      and `crm`.
    - **Runs**: see the `Run` schema for the automations that produce runs.

    - **Webhook events**: `lead.created`, `run.completed` and
      `automation.status_changed`.


    ## Conventions


    - **Identifiers** are opaque strings prefixed by their type: `aut_`
      (automation), `agt_` (agent), `run_` (run), `lea_` (lead), `whk_`
      (webhook subscription), `evt_` (event). Store them and send them back
      unchanged; never validate or parse them (length, alphabet). They are not
      UUIDs.
    - **Dates** are ISO 8601, in UTC, with the `Z` suffix.

    - **Unknown query parameters** are ignored, never rejected, so that a
      client written for a later version keeps working.
    - **Request bodies** are JSON, sent with `Content-Type: application/json`,
      and limited to 16 KB. Another content type is refused with HTTP `415`,
      a larger body with HTTP `413`, both with the code `invalid_request`.
    - **Caching**: every response carries `Cache-Control: no-store`, because
      responses contain personal data.


    ## Pagination


    Lists are paginated with an opaque cursor. `limit` takes a value from 1 to

    100 (25 by default); a value out of range is refused with `400`, not

    corrected. A page looks like

    `{ "data": [...], "has_more": true, "next_cursor": "..." }`: to get the

    next page, send `next_cursor` back as `cursor`. A missing or empty

    `cursor`, or the literal word `null`, means the first page.

    `GET /webhooks` is not paginated.



    ## Rate limits


    - Each API key can make about 100 requests per minute. Requests are
      counted per server instance, so this limit is approximate.
    - Responses carry `X-RateLimit-Limit`, `X-RateLimit-Remaining` and
      `X-RateLimit-Reset` (seconds until the window resets, not a timestamp),
      `401` and `403` responses included.
    - Above the limit, the API answers `429 rate_limited` with a `Retry-After`
      header, in seconds.
    - More than 30 authentication failures per minute from the same IP address
      also lead to `429`. This never applies to requests made with a valid
      key.


    ## Errors


    Every 4xx and 5xx response has the same body:

    `{ "error": { "code": "...", "message": "...", "details": {} } }`.


    - `code` is stable and comes from a closed list (`ErrorCode`): branch on
      it.
    - `message` is in English, meant to be shown to a person, and can change
      at any time.
    - `details` is always an object: empty, or giving context such as the
      faulty `parameter` and a `reason`.

    | HTTP status | `code` | Meaning |

    |---|---|---|

    | 400 | `invalid_request` | Invalid query parameter or body
    (`details.parameter`) |

    | 413, 415 | `invalid_request` | Body larger than 16 KB, or unsupported
    content type (`details.reason`) |

    | 401 | `invalid_api_key` | Missing, malformed, unknown or revoked key |

    | 403 | `workspace_access_denied` | The workspace's subscription does not
    allow API access |

    | 404 | `automation_not_found` | No such automation in this workspace |

    | 404 | `webhook_not_found` | No such webhook subscription in this workspace
    |

    | 404 | `route_not_found` | Unknown path or method under `/v1` (never `405`)
    |

    | 422 | `automation_not_controllable` | `PATCH` on an automation in `draft`
    or `error` (`details.status`), or resuming an e-mail automation whose
    mailbox another active agent already uses (`details.reason: account_in_use`)
    |

    | 429 | `rate_limited` | Rate limit exceeded: wait `Retry-After` seconds |

    | 500 | `internal_error` | Unexpected error (generic message) |

    | 503 | `service_unavailable` | The API is temporarily switched off by
    Agentova: retry later |



    ## Webhooks


    Create a subscription with `POST /webhooks`. Agentova then sends every

    event of the subscribed types as a `POST` request to your URL; the body is

    described by the `delivery` callback of `POST /webhooks`.


    - **Request**: a `POST` with `Content-Type: application/json` and
      `User-Agent: Agentova-Webhooks/1.0`.
    - **Signature**: each delivery carries
      `X-Agentova-Signature: t=<unix timestamp>,v1=<hex digest>`. The digest
      is the HMAC-SHA256 of the string `{t}.{raw request body}`, keyed with the
      complete subscription `secret`, `whsec_` prefix included. Compare digests
      in constant time, and reject a delivery whose `t` is more than 5 minutes
      away from your clock (recommended tolerance). The official Zapier app
      accepts 1 hour, because Zapier can process hooks late and the hook URL
      is itself a secret.
    - **Success** is a 2xx status received within 10 seconds (a deadline for
      the whole response). The response body is ignored. Redirects are not
      followed: a 3xx is a failure.
    - **Retries**: 8 attempts spread over about 27 hours 35 minutes. The first
      attempt is immediate; after each failure, the next one comes 5 seconds,
      5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours and finally 10 hours
      later. When your endpoint answers `429` or `503` with a `Retry-After`
      header, the next attempt waits at least that long, up to 12 hours. No
      attempt is ever scheduled more than 36 hours after the event was
      created: when the next one would be, the delivery is abandoned.
    - **`410 Gone`** deletes the subscription immediately, without any
      notification: answer `410` to unsubscribe (this is how Zapier reports a
      deleted Zap).
    - **Disabling**: a delivery is abandoned after its 8th failed attempt, or
      earlier when it reaches the 36-hour limit. The
      subscription is then disabled if it has at least 3 abandoned deliveries
      in a row and has been failing without interruption for at least 72
      hours. It is also disabled at once, without any delivery, if its URL no
      longer passes the address checks (an IP address that became forbidden).
      Workspace admins are notified in the app and by push
      notification. A disabled subscription receives nothing and cannot be
      re-enabled: delete it and create a new one (Zapier: turn the Zap off and
      on again; n8n: deactivate and reactivate the workflow). Disabled
      subscriptions are deleted automatically 30 days after being disabled.
    - **At least once, in no guaranteed order**: the same event can be
      delivered more than once, and events can arrive out of order.
      Deduplicate on the event `id` (`evt_…`): it is the same on every attempt
      and for every subscription that receives the event; keep the ids you
      have seen for at least 48 hours: retries are always scheduled within 36
      hours of the event's creation. To order events,
      use the timestamp of the resource in `data` (`updated_at` of an
      automation, `created_at` of a lead, `occurred_at` of a run), not the
      arrival order.
    - **Ownership**: subscriptions belong to the workspace; workspace admins
      see and delete them in Settings → API. Revoking the key that created a
      subscription deletes the subscription as well, unless the admin unticks
      that option in Settings → API. A key is also revoked, with its
      subscriptions, when the admin who created it leaves the workspace,
      loses the admin role or deletes their account.
    - **Retention**: the webhook delivery log is kept for 30 days, and runs
      for 90 days.
    - **While the API is switched off** (`503 service_unavailable`), no
      delivery is created for the events that happen in the meantime, and the
      deliveries already in progress are suspended: they resume when the API
      is back. Catch up on the missed events with the list endpoints.


    ## Support


    Documentation: https://docs.agentova.ai. Contact: contact@agentova.ai.
servers:
  - url: https://core-api.agentova.ai/v1
    description: Production, the only environment (there is no separate test environment)
security:
  - bearerAuth: []
paths:
  /webhooks:
    get:
      summary: List webhook subscriptions
      description: >
        Lists all the webhook subscriptions of the workspace, whichever API key
        created them, including disabled ones (`disabled_at` set) until they are
        deleted automatically, 30 days after being disabled. Not paginated. The
        full `url` is returned only for the subscriptions created with the
        calling API key; for the others, `url` is reduced to its origin (for
        example `https://hooks.zapier.com`), since the path of a hook URL
        carries the connector's secret token.
      operationId: listWebhooks
      responses:
        '200':
          description: The subscriptions of the workspace
          headers:
            Cache-Control:
              $ref: '#/components/headers/Cache-Control'
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Webhook'
              example:
                data:
                  - id: whk_01HZX6X7Y8Z9A0B1C2D3E4F5G6
                    url: https://hooks.zapier.com/hooks/standard/xxxxx/
                    events:
                      - lead.created
                    created_at: '2026-08-20T09:25:00Z'
                    disabled_at: null
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  headers:
    Cache-Control:
      description: Always `no-store` (personal data, no intermediate cache)
      schema:
        type: string
        enum:
          - no-store
    X-RateLimit-Limit:
      description: >
        Number of requests allowed per window (per key; per IP address when the
        429 comes from repeated authentication failures)
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Requests left in the current window
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Seconds left before the window resets (NOT a timestamp)
      schema:
        type: integer
  schemas:
    Webhook:
      type: object
      description: >
        A webhook subscription. It belongs to the workspace. Revoking the API
        key that created it deletes it as well, unless the admin unticks that
        option in Settings → API.
      required:
        - id
        - url
        - events
        - created_at
        - disabled_at
      properties:
        id:
          type: string
          description: Opaque identifier prefixed with `whk_`.
        url:
          type: string
          format: uri
          description: URL that receives the deliveries.
        events:
          type: array
          description: Event types sent to this URL.
          items:
            $ref: '#/components/schemas/WebhookEvent'
        created_at:
          type: string
          format: date-time
          description: When the subscription was created.
        disabled_at:
          type: string
          format: date-time
          nullable: true
          description: >
            Set when Agentova disabled the subscription, typically after
            prolonged delivery failures (see `POST /webhooks`); `null`
            otherwise. A disabled subscription receives nothing and cannot be
            re-enabled: delete it and create a new one. It is deleted
            automatically 30 days after this date.
    WebhookEvent:
      type: string
      description: |
        - `lead.created`: a lead was created (`data` is a `Lead`).
        - `run.completed`: an automation completed a run (`data` is a `Run`).
        - `automation.status_changed`: the status of an automation changed
          (`data` is an `Automation`).
      enum:
        - run.completed
        - lead.created
        - automation.status_changed
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - details
          properties:
            code:
              $ref: '#/components/schemas/ErrorCode'
            message:
              type: string
              description: >
                In English, meant to be displayed; it can change without notice
                (branch on `code`).
            details:
              type: object
              description: >
                Empty (`{}`) or context: `parameter`, `allowed`, `max`,
                `reason`, `status`, `retry_after_seconds`…
    ErrorCode:
      type: string
      description: >
        Stable error codes. `invalid_request` (400; also 413 when the body is
        larger than 16 KB and 415 for an unsupported content type: the HTTP
        status is kept and the cause is in `details.reason`) · `invalid_api_key`
        (401) · `workspace_access_denied` (403) · `automation_not_found` (404) ·
        `webhook_not_found` (404) · `route_not_found` (404: unknown path or
        method) · `automation_not_controllable` (422: automation in `draft` or
        `error`, see `details.status`) · `rate_limited` (429) · `internal_error`
        (500, generic message) · `service_unavailable` (503: the API is
        temporarily switched off by Agentova; retry later).
      enum:
        - invalid_request
        - invalid_api_key
        - workspace_access_denied
        - automation_not_found
        - webhook_not_found
        - route_not_found
        - automation_not_controllable
        - rate_limited
        - internal_error
        - service_unavailable
  responses:
    Unauthorized:
      description: >-
        Missing, malformed, unknown or revoked key (deliberately
        indistinguishable)
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: invalid_api_key
              message: Invalid or revoked key — create one in Settings → API
              details: {}
    Forbidden:
      description: >
        Valid key, but the workspace does not have access to the service (or no
        longer has it): its subscription is blocked (unpaid, paused, or initial
        payment never completed). A workspace without a subscription is on the
        free plan and is not affected. This is not a per-key permission: v1 has
        no per-key permissions.
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: workspace_access_denied
              message: This workspace's subscription does not allow access to the API
              details: {}
    RateLimited:
      description: >
        Rate limit exceeded: too many requests with this key, or too many
        authentication failures from this IP address
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
        Retry-After:
          description: Seconds to wait before retrying
          schema:
            type: integer
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: rate_limited
              message: Rate limit exceeded — retry in a few seconds
              details:
                retry_after_seconds: 42
    ServiceUnavailable:
      description: >
        The API is temporarily switched off by Agentova (`service_unavailable`):
        retry later. This response may come without the `X-RateLimit-*` headers.
        While the API is switched off, no webhook delivery is created for the
        events that happen in the meantime.
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: service_unavailable
              message: The API is temporarily unavailable — retry later
              details: {}
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: agk_live_<32 characters>
      description: >
        API key created in the Agentova app (Settings → API), sent as
        `Authorization: Bearer agk_live_…`. One key = one workspace: the key
        determines the workspace, and no workspace identifier ever travels in
        requests. The `Bearer` scheme is case-insensitive. A revoked key is
        refused immediately.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.