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

# Cancel phone line

> ⚠️ **Real side effect — this is NOT a simulation, including from the playground.** Cancels the line and answers the line **as it is afterwards**. What happens depends on its `status`:

| `status` before | Result | Response |
| --- | --- | --- |
| `ACTIVE` | **Cancelled at period end, no refund.** The line stays `ACTIVE` and fully usable — activation codes included — until `currentPeriodEnd`; it is not renewed and becomes `CANCELED` when the period ends. | `200`, `status: "ACTIVE"`, `cancelAtPeriodEnd: true` |
| `ACTIVE`, already cancelled | Nothing changes — calling again is safe. | `200`, same line |
| `PAYMENT_PENDING`, `SUSPENDED` | **Returned to the carrier immediately — IRREVERSIBLE.** There is no paid period left. | `200`, `status: "RETURNED"` |
| `RETURNED`, `CANCELED` | Refused — the line is already finished. | `409 NOT_CANCELABLE` |

**A returned number stops being yours**: nothing undoes a return, and there is **no guarantee it can be bought back** — it goes back to the carrier's pool, where anyone may rent it next. The WhatsApp account activated on it stays tied to that number. The line's code history — codes and call recordings — is deleted. Cancelling an unpaid line does this **at once**, with no grace period. Undoing a scheduled cancellation of an `ACTIVE` line is dashboard-only (Owner).

If a return of the same unpaid line is already under way (hourly billing run, or the dashboard's **Choose which lines to keep**), the call answers `200` with the line as it stands — possibly still `PAYMENT_PENDING` or `SUSPENDED` — and that process completes the return. Events: `phone_line.canceled` when a line cancelled at period end becomes `CANCELED`; `phone_line.returned` with `reason: "canceled_by_customer"` right away for an unpaid line returned by this call.

Permissions: with an OAuth / MCP token, only the workspace **Owner** may cancel (`phone_lines:cancel`) — `403 PERMISSION_DENIED` otherwise.

Every `/v1/phone-lines` endpoint takes a **tenant-scoped** key only: a line belongs 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`.

**Requires a tenant-scoped key.**

> [!WARNING]
>
> **This cancels the line for real.** An `ACTIVE` line is cancelled at the end of its period, with no refund. An unpaid line (`PAYMENT_PENDING`, `SUSPENDED`) is **returned to the carrier at once**, with no guarantee it can be bought back, and its code history is deleted. See [Cancel a line](https://docs.pilotstatus.com.br/api/phone-lines/cancel.md).


## OpenAPI

````yaml openapi.json DELETE /v1/phone-lines/{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/{id}:
    delete:
      tags:
        - Phone Lines
      summary: Cancel a phone line
      description: >-
        ⚠️ **Real side effect — this is NOT a simulation, including from the
        playground.** Cancels the line and answers the line **as it is
        afterwards**. What happens depends on its `status`:


        | `status` before | Result | Response |

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

        | `ACTIVE` | **Cancelled at period end, no refund.** The line stays
        `ACTIVE` and fully usable — activation codes included — until
        `currentPeriodEnd`; it is not renewed and becomes `CANCELED` when the
        period ends. | `200`, `status: "ACTIVE"`, `cancelAtPeriodEnd: true` |

        | `ACTIVE`, already cancelled | Nothing changes — calling again is safe.
        | `200`, same line |

        | `PAYMENT_PENDING`, `SUSPENDED` | **Returned to the carrier immediately
        — IRREVERSIBLE.** There is no paid period left. | `200`, `status:
        "RETURNED"` |

        | `RETURNED`, `CANCELED` | Refused — the line is already finished. |
        `409 NOT_CANCELABLE` |


        **A returned number stops being yours**: nothing undoes a return, and
        there is **no guarantee it can be bought back** — it goes back to the
        carrier's pool, where anyone may rent it next. The WhatsApp account
        activated on it stays tied to that number. The line's code history —
        codes and call recordings — is deleted. Cancelling an unpaid line does
        this **at once**, with no grace period. Undoing a scheduled cancellation
        of an `ACTIVE` line is dashboard-only (Owner).


        If a return of the same unpaid line is already under way (hourly billing
        run, or the dashboard's **Choose which lines to keep**), the call
        answers `200` with the line as it stands — possibly still
        `PAYMENT_PENDING` or `SUSPENDED` — and that process completes the
        return. Events: `phone_line.canceled` when a line cancelled at period
        end becomes `CANCELED`; `phone_line.returned` with `reason:
        "canceled_by_customer"` right away for an unpaid line returned by this
        call.


        Permissions: with an OAuth / MCP token, only the workspace **Owner** may
        cancel (`phone_lines:cancel`) — `403 PERMISSION_DENIED` otherwise.


        Every `/v1/phone-lines` endpoint takes a **tenant-scoped** key only: a
        line belongs 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`.


        **Requires a tenant-scoped key.**
      operationId: delete_phone_lines_id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          example: cmg5k2l1n0001pl8example9x
          description: >-
            The line's `id` (from `GET /v1/phone-lines`, or `lineId` in the
            purchase result) — not the phone number.
      responses:
        '200':
          description: The line as it is after the call
          content:
            application/json:
              schema:
                type: object
                properties:
                  line:
                    type: object
                    properties:
                      id:
                        type: string
                        description: >-
                          The line id. Use it in every `/v1/phone-lines/{id}`
                          path.
                        example: cmg5k2l1n0001pl8example9x
                      name:
                        type: string
                        description: >-
                          The name your team gave the line in the dashboard, up
                          to 60 characters. **Never empty:** a line without a
                          name returns its formatted number, the same as
                          `display` — and every line is bought without one. It
                          cannot be set or changed through the API. It is a
                          label: identify the line by its `id`.
                        example: Support SP
                      number:
                        type: string
                        description: E.164 digits **without** `+`, e.g. `551148637200`.
                        example: '551148637200'
                      display:
                        type: string
                        description: 'The number formatted for people: `(11) 4863-7200`.'
                        example: (11) 4863-7200
                      ddd:
                        type: string
                        description: The two-digit area code.
                        example: '11'
                      status:
                        type: string
                        description: >-
                          `ACTIVE`, `PAYMENT_PENDING`, `SUSPENDED`, `RETURNED`
                          or `CANCELED`. The field to branch on.
                        example: ACTIVE
                        enum:
                          - ACTIVE
                          - PAYMENT_PENDING
                          - SUSPENDED
                          - RETURNED
                          - CANCELED
                      price:
                        type: number
                        description: >-
                          What **this** line costs per month — the price of its
                          next renewal (e.g. `33.9`): the purchase price, or the
                          workspace's own phone line price when the Pilot Status
                          team set one (applied to lines bought before it too).
                        example: 33.9
                      currency:
                        type: string
                        description: '`BRL` or `USD` — the currency `price` is charged in.'
                        example: BRL
                        enum:
                          - BRL
                          - USD
                      purchasedAt:
                        type: string
                        description: >-
                          ISO 8601 — when the line was bought. Renewals count
                          from it.
                        example: '2026-10-01T14:03:11.000Z'
                        format: date-time
                      currentPeriodEnd:
                        type: string
                        description: >-
                          ISO 8601 — end of the paid period. The next renewal is
                          attempted in the first hourly billing run after it.
                          For a line cancelled at period end, when it becomes
                          `CANCELED`. It does not move while a renewal is
                          unpaid.
                        example: '2026-11-01T14:03:11.000Z'
                        format: date-time
                      cancelAtPeriodEnd:
                        type: boolean
                        description: >-
                          `true` after a `DELETE` on an `ACTIVE` line: it will
                          not renew and becomes `CANCELED` at
                          `currentPeriodEnd`.
                        example: false
                      paymentPendingSince:
                        type:
                          - string
                          - 'null'
                        description: >-
                          ISO 8601 — when the renewal charge failed. The line is
                          suspended 2 days after this. `null` once a renewal
                          succeeds.
                        example: null
                        format: date-time
                      suspendedAt:
                        type:
                          - string
                          - 'null'
                        description: >-
                          ISO 8601 — when the line was suspended. It is returned
                          1 day after this. `null` once a renewal succeeds.
                        example: null
                        format: date-time
                      returnedAt:
                        type:
                          - string
                          - 'null'
                        description: >-
                          ISO 8601 — when the number was returned to the carrier
                          (`RETURNED`).
                        example: null
                        format: date-time
                      canceledAt:
                        type:
                          - string
                          - 'null'
                        description: >-
                          ISO 8601 — when a line cancelled at period end became
                          `CANCELED`.
                        example: null
                        format: date-time
                      activationCount:
                        type: integer
                        description: >-
                          How many code requests were opened on this line so
                          far. A `POST …/activations` that answered `503` is not
                          counted.
                        example: 1
                      amountDue:
                        type:
                          - number
                          - 'null'
                        description: >-
                          On a `PAYMENT_PENDING` or `SUSPENDED` line, what
                          paying it now charges — the amount of its overdue
                          period, fixed when that period was first charged.
                          `null` on any other line.
                        example: null
              examples:
                paidLine:
                  summary: 'Paid line: cancelled at period end'
                  value:
                    line:
                      id: cmg5k2l1n0001pl8example9x
                      name: Support SP
                      number: '551148637200'
                      display: (11) 4863-7200
                      ddd: '11'
                      status: ACTIVE
                      price: 33.9
                      currency: BRL
                      purchasedAt: '2026-10-01T14:03:11.000Z'
                      currentPeriodEnd: '2026-11-01T14:03:11.000Z'
                      cancelAtPeriodEnd: true
                      paymentPendingSince: null
                      suspendedAt: null
                      returnedAt: null
                      canceledAt: null
                      activationCount: 1
                      amountDue: null
                unpaidLine:
                  summary: 'Unpaid line: returned now'
                  value:
                    line:
                      id: cmg5k2l1n0001pl8example9x
                      name: Support SP
                      number: '551148637200'
                      display: (11) 4863-7200
                      ddd: '11'
                      status: RETURNED
                      price: 33.9
                      currency: BRL
                      purchasedAt: '2026-10-01T14:03:11.000Z'
                      currentPeriodEnd: '2026-11-01T14:03:11.000Z'
                      cancelAtPeriodEnd: false
                      paymentPendingSince: '2026-11-01T14:17:02.000Z'
                      suspendedAt: null
                      returnedAt: '2026-11-02T09:41:27.000Z'
                      canceledAt: null
                      activationCount: 1
                      amountDue: null
        '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 the workspace Owner (`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 the Owner
                  value:
                    error: >-
                      Your workspace role does not allow this action
                      (phone_lines:cancel).
                    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 line in your workspace (`LINE_NOT_FOUND`) — a line of
            another workspace answers the same and is left untouched
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              examples:
                lineNotFound:
                  summary: No such line in your workspace
                  value:
                    error: Line not found. | Linha não encontrada.
                    code: LINE_NOT_FOUND
                numberHeader:
                  summary: '`x-whatsapp-number-id` names no number'
                  value:
                    error: >-
                      x-whatsapp-number-id does not name a WhatsApp number of
                      this account | x-whatsapp-number-id não indica um número
                      de WhatsApp desta conta
                    code: NUMBER_NOT_FOUND
        '409':
          description: The line is already `RETURNED` or `CANCELED` (`NOT_CANCELABLE`)
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              example:
                error: >-
                  This line cannot be cancelled now. | Esta linha não pode ser
                  cancelada agora.
                code: NOT_CANCELABLE
        '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
        '503':
          description: >-
            Unpaid line only: the carrier did not confirm the return
            (`SUPPLIER_UNAVAILABLE`). **This call did not change the line** —
            retry in a few minutes.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              example:
                error: >-
                  Phone lines are temporarily unavailable. Try again in a few
                  minutes. | As linhas estão temporariamente indisponíveis.
                  Tente de novo em alguns minutos.
                code: SUPPLIER_UNAVAILABLE
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.