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

# List workspace webhooks

> **Workspace webhooks** — the same registry as `/v1/phone-lines/webhooks` (same rows, `plwh_` secret, signature, retries and deliveries), with a wider event set: every `phone_line.*` event **plus `wallet.topup_paid`** (a wallet top-up was credited). `"*"` means every phone-line event only: `wallet.topup_paid` is opt-in, list it by name (for example `["*", "wallet.topup_paid"]`). This surface lists every webhook of the workspace. Tenant-scoped key (or account key with `x-workspace-id`); Owner or Admin (`phone_lines:webhooks`) with a user credential.

Returns `{ "webhooks": [ … ], "events": [ … ] }`: every phone-line webhook of your workspace, **oldest first**, and the catalogue of events you can subscribe to. **The signing secret is never returned here** — only once, by `POST /v1/workspace/webhooks`.

Permissions: with an OAuth / MCP token, the user must be an **Owner or Admin** (`phone_lines:webhooks`) — `403 PERMISSION_DENIED` otherwise.

Every `/v1/phone-lines` endpoint takes a **tenant-scoped** key only: phone-line webhooks belong to the workspace, not to a WhatsApp number, so a number-scoped key (or a per-number OAuth grant) gets `403 NUMBER_SCOPE_NOT_ALLOWED` before any role is looked at. A `403 PERMISSION_DENIED` / `WORKSPACE_MEMBERSHIP_REQUIRED` is sent with `Cache-Control: no-store`.

These are the **phone-line webhooks** — a registry separate from `/v1/webhooks`: they receive only `phone_line.*` events, and a number webhook never receives one.

**Requires a tenant-scoped key.**



## OpenAPI

````yaml openapi.json GET /v1/workspace/webhooks
openapi: 3.1.0
info:
  title: Pilot Status API
  version: 1.0.0
  license:
    name: Pilot Status Terms of Service
    url: https://pilotstatus.com.br/terms
  description: >-
    Public REST API for Pilot Status. Authenticate with the `x-api-key: ps_...`
    header (or `x-api-key-id`). Base URL: https://pilotstatus.com.br
servers:
  - url: https://pilotstatus.com.br
security:
  - apiKey: []
  - apiKeyId: []
paths:
  /v1/workspace/webhooks:
    get:
      tags:
        - Workspace
      summary: List workspace webhooks
      description: >-
        **Workspace webhooks** — the same registry as `/v1/phone-lines/webhooks`
        (same rows, `plwh_` secret, signature, retries and deliveries), with a
        wider event set: every `phone_line.*` event **plus `wallet.topup_paid`**
        (a wallet top-up was credited). `"*"` means every phone-line event only:
        `wallet.topup_paid` is opt-in, list it by name (for example `["*",
        "wallet.topup_paid"]`). This surface lists every webhook of the
        workspace. Tenant-scoped key (or account key with `x-workspace-id`);
        Owner or Admin (`phone_lines:webhooks`) with a user credential.


        Returns `{ "webhooks": [ … ], "events": [ … ] }`: every phone-line
        webhook of your workspace, **oldest first**, and the catalogue of events
        you can subscribe to. **The signing secret is never returned here** —
        only once, by `POST /v1/workspace/webhooks`.


        Permissions: with an OAuth / MCP token, the user must be an **Owner or
        Admin** (`phone_lines:webhooks`) — `403 PERMISSION_DENIED` otherwise.


        Every `/v1/phone-lines` endpoint takes a **tenant-scoped** key only:
        phone-line webhooks belong to the workspace, not to a WhatsApp number,
        so a number-scoped key (or a per-number OAuth grant) gets `403
        NUMBER_SCOPE_NOT_ALLOWED` before any role is looked at. A `403
        PERMISSION_DENIED` / `WORKSPACE_MEMBERSHIP_REQUIRED` is sent with
        `Cache-Control: no-store`.


        These are the **phone-line webhooks** — a registry separate from
        `/v1/webhooks`: they receive only `phone_line.*` events, and a number
        webhook never receives one.


        **Requires a tenant-scoped key.**
      operationId: get_workspace_webhooks
      parameters:
        - name: x-workspace-id
          in: header
          required: false
          schema:
            type: string
          description: >-
            Only with an account key (`ps_account_`): the workspace to act on,
            from `GET /v1/workspaces`. Without it an account key gets `400
            WORKSPACE_ID_REQUIRED`.
          example: cmh2a9z8y0002ws8example1q
      responses:
        '200':
          description: The webhooks and the event catalogue
          content:
            application/json:
              schema:
                type: object
                properties:
                  webhooks:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: >-
                            The webhook id. Use it in every
                            `/v1/phone-lines/webhooks/{id}` path.
                          example: cmh1w8b2k0001wh8example3d
                        name:
                          type: string
                          description: >-
                            Up to 100 characters. **Never empty:** created or
                            edited blank, it is the URL's host
                            (`hooks.example.com`). Not sent in deliveries — the
                            `name` of a delivery is the line's.
                          example: hooks.example.com
                        url:
                          type: string
                          description: The `https` destination, normalized.
                          example: https://hooks.example.com/pilot/phone-lines
                        events:
                          type: array
                          items:
                            type: string
                          description: >-
                            The subscribed events, or `["*"]` — every phone-line
                            event, including any added later.
                          example:
                            - '*'
                        active:
                          type: boolean
                          description: '`false` = paused: receives no deliveries.'
                          example: true
                        lastDeliveryAt:
                          type:
                            - string
                            - 'null'
                          format: date-time
                          description: >-
                            ISO 8601 — the last **successful** delivery, `null`
                            before the first. A failed attempt does not change
                            it.
                          example: '2026-10-27T14:11:51.000Z'
                        lastStatusCode:
                          type:
                            - integer
                            - 'null'
                          description: >-
                            The last HTTP status your endpoint answered,
                            successful or not, `null` when none.
                          example: 200
                        createdAt:
                          type: string
                          format: date-time
                          description: ISO 8601 — when the webhook was created.
                          example: '2026-10-27T13:58:02.000Z'
                  events:
                    type: array
                    items:
                      type: string
                    description: >-
                      Every phone-line event name. `"*"` is not in the list but
                      is accepted in `events`.
                    example:
                      - phone_line.purchased
                      - phone_line.audio_received
                      - phone_line.code_received
                      - phone_line.code_failed
                      - phone_line.renewed
                      - phone_line.payment_failed
                      - phone_line.suspended
                      - phone_line.returned
                      - phone_line.canceled
                      - phone_line.verification_updated
              example:
                webhooks:
                  - id: cmh1w8b2k0001wh8example3d
                    name: hooks.example.com
                    url: https://hooks.example.com/pilot/phone-lines
                    events:
                      - '*'
                    active: true
                    lastDeliveryAt: '2026-10-27T14:11:51.000Z'
                    lastStatusCode: 200
                    createdAt: '2026-10-27T13:58:02.000Z'
                events:
                  - phone_line.purchased
                  - phone_line.audio_received
                  - phone_line.code_received
                  - phone_line.code_failed
                  - phone_line.renewed
                  - phone_line.payment_failed
                  - phone_line.suspended
                  - phone_line.returned
                  - phone_line.canceled
                  - phone_line.verification_updated
                  - wallet.topup_paid
        '401':
          description: >-
            Missing or invalid credential (`x-api-key`, `x-api-key-id` or
            `Authorization: Bearer`). The body carries only `error`, no `code`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              examples:
                missing:
                  summary: No credential
                  value:
                    error: >-
                      Missing x-api-key, x-api-key-id or Authorization Bearer
                      token
                invalid:
                  summary: Invalid API key
                  value:
                    error: Invalid API key
        '403':
          description: >-
            Number-scoped key (`NUMBER_SCOPE_NOT_ALLOWED`), OAuth/MCP token of a
            user who is not Owner or Admin (`PERMISSION_DENIED`) or no longer an
            active member (`WORKSPACE_MEMBERSHIP_REQUIRED`), or archived
            workspace (`WORKSPACE_ARCHIVED`). `TENANT_REQUIRED`: credential not
            bound to any workspace
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              examples:
                numberScope:
                  summary: Number-scoped key
                  value:
                    error: This endpoint requires a tenant-scoped API key
                    code: NUMBER_SCOPE_NOT_ALLOWED
                permissionDenied:
                  summary: OAuth/MCP user who is not Owner or Admin
                  value:
                    error: >-
                      Your workspace role does not allow this action
                      (phone_lines:webhooks).
                    code: PERMISSION_DENIED
                notMember:
                  summary: OAuth/MCP user no longer a member
                  value:
                    error: >-
                      The user behind this token is not an active member of this
                      workspace.
                    code: WORKSPACE_MEMBERSHIP_REQUIRED
                archived:
                  summary: Workspace archived
                  value:
                    error: >-
                      This workspace has been archived and its API is closed. |
                      Este workspace foi arquivado e sua API está encerrada.
                    code: WORKSPACE_ARCHIVED
                tenantRequired:
                  summary: Credential not bound to a workspace
                  value:
                    error: This credential is not bound to a workspace.
                    code: TENANT_REQUIRED
        '500':
          description: Unexpected failure (`INTERNAL_ERROR`).
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              example:
                error: Unexpected error. | Erro inesperado.
                code: INTERNAL_ERROR
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: Your ps_ API key
    apiKeyId:
      type: apiKey
      in: header
      name: x-api-key-id
      description: API key id (alternative to x-api-key)

````

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