> ## 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.

# Update line webhook

> ⚠️ **Real side effect.** Changes the fields you send and answers `{ "webhook": { … } }`; an absent field is left as it is. `active: false` **pauses** the webhook (it receives no deliveries — a delivery already in its retries is marked failed at its next attempt) and `active: true` resumes it; events that happened while it was paused are never sent.

The resulting webhook is validated as on creation. **Only a URL that changes is checked again** against internal destinations, so a webhook can always be paused or have its events edited. A `name` sent blank becomes the host of the (new or stored) URL. **Editing never changes the signing secret**, and the secret is not returned.

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 PATCH /v1/phone-lines/webhooks/{id}
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/phone-lines/webhooks/{id}:
    patch:
      tags:
        - Phone Lines
      summary: Update or pause a phone-line webhook
      description: >-
        ⚠️ **Real side effect.** Changes the fields you send and answers `{
        "webhook": { … } }`; an absent field is left as it is. `active: false`
        **pauses** the webhook (it receives no deliveries — a delivery already
        in its retries is marked failed at its next attempt) and `active: true`
        resumes it; events that happened while it was paused are never sent.


        The resulting webhook is validated as on creation. **Only a URL that
        changes is checked again** against internal destinations, so a webhook
        can always be paused or have its events edited. A `name` sent blank
        becomes the host of the (new or stored) URL. **Editing never changes the
        signing secret**, and the secret is not returned.


        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: patch_phone_lines_webhooks_id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          example: cmh1w8b2k0001wh8example3d
          description: >-
            The webhook's `id` (from `GET /v1/phone-lines/webhooks` or the
            create response).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                name:
                  type: string
                  maxLength: 100
                  description: >-
                    Optional, up to 100 characters (`400 INVALID_WEBHOOK_NAME`
                    above that). Blank or absent → the URL's host.
                  example: Phone lines — production
                url:
                  type: string
                  description: >-
                    Must be `https` and reach a public address. A URL that
                    points to an internal or private network address —
                    `localhost`, a loopback or private IP, a host without a dot,
                    or a name that resolves to one — → `400
                    WEBHOOK_URL_REFUSED`.
                  example: https://hooks.example.com/pilot/phone-lines
                events:
                  type: array
                  minItems: 1
                  items:
                    type: string
                    enum:
                      - 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
                      - '*'
                  description: >-
                    One or more of the phone-line events, or `"*"` for all of
                    them (inside this registry `"*"` means every phone-line
                    event, including any added later). Duplicates are removed.
                    An empty list or an unknown event → `400 INVALID_WEBHOOK`.
                  example:
                    - '*'
                active:
                  type: boolean
                  description: '`false` pauses, `true` resumes.'
                  example: false
            example:
              active: false
      responses:
        '200':
          description: The webhook after the change
          content:
            application/json:
              schema:
                type: object
                properties:
                  webhook:
                    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'
              example:
                webhook:
                  id: cmh1w8b2k0001wh8example3d
                  name: hooks.example.com
                  url: https://hooks.example.com/pilot/phone-lines
                  events:
                    - '*'
                  active: false
                  lastDeliveryAt: '2026-10-27T14:11:51.000Z'
                  lastStatusCode: 200
                  createdAt: '2026-10-27T13:58:02.000Z'
        '400':
          description: >-
            Invalid request: body not a JSON object (`INVALID_BODY`), fields
            other than `name`, `url`, `events` and `active` (`UNKNOWN_FIELDS`,
            `details.unknownFields`), a field with the wrong JSON type
            (`INVALID_FIELD_TYPE`, `details.field` / `details.expected`), a URL
            that is not `https` or an empty / unknown event list
            (`INVALID_WEBHOOK`), a `name` over 100 characters
            (`INVALID_WEBHOOK_NAME`), or a URL that points to an internal or
            private network address (`WEBHOOK_URL_REFUSED`)
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
                  details:
                    type: object
              examples:
                invalidBody:
                  summary: Body is not a JSON object
                  value:
                    error: >-
                      Send a JSON object: { "active": false }. | Envie um objeto
                      JSON: { "active": false }.
                    code: INVALID_BODY
                unknownFields:
                  summary: Unknown field
                  value:
                    error: >-
                      Unknown field(s): secret. Accepted: name, url, events,
                      active. | Campo(s) desconhecido(s): secret. Aceitos: name,
                      url, events, active.
                    code: UNKNOWN_FIELDS
                    details:
                      unknownFields:
                        - secret
                invalidFieldType:
                  summary: Field with the wrong type
                  value:
                    error: >-
                      "active" must be true or false. | "active" deve ser true
                      ou false.
                    code: INVALID_FIELD_TYPE
                    details:
                      field: active
                      expected: boolean
                invalidWebhook:
                  summary: Not https, or empty / unknown events
                  value:
                    error: >-
                      Invalid webhook: use an https URL and known events. |
                      Webhook inválido: use uma URL https e eventos conhecidos.
                    code: INVALID_WEBHOOK
                invalidName:
                  summary: Name over 100 characters
                  value:
                    error: >-
                      Invalid webhook name: use at most 100 characters. | Nome
                      do webhook inválido: use no máximo 100 caracteres.
                    code: INVALID_WEBHOOK_NAME
                urlRefused:
                  summary: Internal or private destination
                  value:
                    error: >-
                      Webhook URL refused: it points to an internal or private
                      network address, which we never call. Use a public
                      address. | URL do webhook recusada: ela aponta para um
                      endereço interno ou de rede privada, que nunca chamamos.
                      Use um endereço público.
                    code: WEBHOOK_URL_REFUSED
        '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
        '404':
          description: >-
            No such webhook in your workspace (`WEBHOOK_NOT_FOUND`) — a webhook
            of another workspace reads the same
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              example:
                error: Webhook not found. | Webhook não encontrado.
                code: WEBHOOK_NOT_FOUND
        '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.