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

# Buy a phone number

> Purchases a number returned by the search endpoint. If the country/type requires compliance, include an address (when needed) and a list of requirement values — text answers and document IDs from /api/v1/phone-numbers/documents. Subject to a per-workspace cap on active numbers purchased via the API; when the cap is reached you receive HTTP 403 with `data.error = purchase_limit_reached` plus the actual `limit` and `current` count in the response body.



## OpenAPI

````yaml https://app.mindhunters.ai/docs/api-docs.json post /api/v1/phone-numbers
openapi: 3.0.0
info:
  title: Mihu API Documentation
  description: >-
    Welcome to Mihu API Documentation for developers.Here you can find all the
    information about the API endpoints and how to use them.If you have any
    questions or need help, please contact us at support@mihu.ai
  version: 1.0.0
servers:
  - url: https://{subdomain}.mihu.ai
    description: Your subdomain
    variables:
      subdomain:
        default: demo
        description: Subdomain name
  - url: /docs
security: []
tags:
  - name: Agents
    description: >-
      Manage AI agents, settings, knowledge sections, rules, appointments, and
      channel provisioning
  - name: Contact Analyzers
    description: >-
      Configure what information should be extracted from conversations and how
      extracted values should update contacts, custom contact fields, or
      pipeline stages. Analyzer IDs use prefixes: `b_` means a built-in contact
      field, `f_` means a custom contact field, and `p_` means a pipeline stage
      rule.
  - name: Appointments
    description: Appointment management endpoints
  - name: Appointment Requests
    description: Appointment request endpoints
  - name: Availability Types
    description: Availability type endpoints
  - name: Call Actions
    description: >-
      Real-time control actions for an active call: say, forward, hangup, mute,
      and unmute. Each action targets a live call by its conversation UUID,
      returned as `conversation_uuid` from POST /api/v1/call. Requires a bearer
      token and a live (non-ended) call.
  - name: Campaigns
    description: Campaign management endpoints
  - name: Contacts
    description: Contact management endpoints
  - name: Contact Approvals
    description: >-
      Manage AI-suggested contact field updates pending human review. Each
      approval is identified by its `uuid`.
  - name: Contact Fields
    description: >-
      Manage custom contact fields for your account. Each field is identified by
      its `key` (unique and immutable once created).
  - name: Contact Settings
    description: >-
      Toggle contact-list display preferences such as masking phone numbers or
      email addresses. Each setting is identified by its `key`.
  - name: Conversations
    description: Conversation management endpoints
  - name: Sessions
    description: Conversation session endpoints
  - name: Tables
    description: >-
      Tables are user-defined datasets that AI agents use as a knowledge base
      (semantic search over text) or as a real-time lookup (structured rows the
      agent queries during conversations).


      **When to create a table.** Create one whenever an agent needs to ground
      its answers in your data: product catalog, FAQ, pricing list, internal
      policies, customer records, business rules, etc. One table = one dataset
      on one topic.


      **How to create + populate.** Pick one of:

      - `POST /api/v1/data/tables` — create an empty table with a typed column
      schema (text/number/date/boolean/json/url). Use this when you have
      structured data and want to add rows yourself via the records endpoints.

      - `POST /api/v1/data/import/copypaste` — paste raw text. Best for FAQs,
      policy docs, or any unstructured knowledge content.

      - `POST /api/v1/data/import/file` — upload CSV/Excel/JSON/PDF/XML/audio.
      Best for spreadsheets, documents, transcripts.

      - `POST /api/v1/data/import/website` — crawl a URL. Best for public
      knowledge bases, marketing sites.


      **Records.** Once a table exists, add/update/delete rows via
      `POST|PUT|DELETE /api/v1/data/{uuid}/records[/{record}]`. Inspect the
      schema with `GET /api/v1/data/{uuid}/fields`.


      **Connecting to an agent.** Call `POST /api/v1/data/{uuid}/assign` to make
      a table available to an agent. After bulk changes, call `POST
      /api/v1/data/{uuid}/sync` to refresh the agent's index.


      **Lifecycle.** create → populate (records or import) → assign to agent →
      agent uses it at runtime → update/sync as data changes → delete when no
      longer needed.
  - name: Logs
    description: >-
      Read-only audit feeds for agent activity. The Actions log is a
      chronological stream of every task, workflow run, and AI action taken
      during a call — what your agents actually did, when, and how long it took.
  - name: Evaluate
    description: >-
      Per-agent and global settings that control how conversations are
      sessionized and analyzed.


      WHAT EVALUATION DOES:

      At runtime, every conversation is grouped into 'sessions' (continuous
      bursts of messages). When a session ends — either because the customer
      goes idle for sessionization.timeout_minutes, or the conversation closes —
      the runtime fires SessionSummaryService and runs each enabled analyzer
      feature against the full session transcript. Outputs are persisted as
      'evaluation' records.


      WHEN IT RUNS:

      - Voice calls and WhatsApp Call: at end of call (or after silence_timeout)

      - SMS, WhatsApp text, Instagram, FB Messenger: when the session creator
      job (SmsSessionCreatorJob / WhatsappSessionCreatorJob / equivalents)
      closes the session

      - Triggered automatically; not on demand


      WHICH CHANNEL'S CONFIG RUNS:

      - text.* features run for sessions on text channels (SMS, WhatsApp text,
      Instagram, FB Messenger, chat)

      - voice.* features run for sessions on voice channels (phone calls,
      WhatsApp Call)

      - Both blocks live on the same settings row; only the relevant one fires
      per session


      WHAT THE FEATURES PRODUCE:

      Each enabled feature emits a classification (one label per session, per
      feature) using its 'description' field as the LLM prompt.
      success_evaluation_prompt is special: it returns true/false based on the
      'prompt' field — leave 'prompt' empty and the result is meaningless.
      summary_prompt is consumed by SessionSummaryService to produce the
      human-readable session summary in report_language.


      WHERE TO READ RESULTS:

      - GET /api/v1/sessions/{uuid}/evaluation — single session result

      - GET /api/v1/evaluations — list, filterable

      - GET /api/v1/analytics/evaluations — aggregated dashboard data


      COST CONSIDERATIONS:

      Each enabled feature is one extra LLM call per session. Disable features
      you don't read. is_active=false disables every analyzer for that agent
      (and skips the summary).


      WORKFLOW:

      1. GET /default to see the workspace-wide config every agent inherits

      2. POST /agents/{uuid}/evaluate/assign to give one agent its own override

      3. PUT /agents/{uuid}/evaluate (or /default) for partial updates

      4. DELETE /agents/{uuid}/evaluate to revert that agent to the default
  - name: Language
    description: Languages available for agent configuration.
  - name: Listings
    description: Listing management endpoints
  - name: Memorize
    description: >-
      Manage what your agents remember from contacts and conversations. There is
      one global default; each agent can optionally override it with its own
      settings.
  - name: Call
    description: Voice call endpoints
  - name: WhatsApp
    description: WhatsApp messaging endpoints
  - name: WhatsApp Calling
    description: WhatsApp voice call endpoints
  - name: SMS
    description: SMS messaging endpoints
  - name: Evaluations
    description: >-
      Evaluations are AI-generated analysis records for conversation sessions.
      Use these endpoints to list or retrieve scores, labels, reasons, and
      linked conversation/contact identifiers for quality review and reporting.
  - name: Schedules
    description: >-
      Schedules are bookable calendars used by agents and appointment flows. A
      schedule links to an availability type, stores assignment metadata, and
      can include custom questions for appointment collection.
  - name: Tasks
    description: >-
      Tasks are scheduled units of work for agents, such as outbound calls and
      WhatsApp template messages. Use task endpoints when you need to inspect
      campaign-generated work, create one-off outreach, queue a task, cancel it,
      or retry a failed attempt.
  - name: Transcriptions
    description: >-
      Transcriptions turn audio files or audio URLs into conversation text,
      session records, and optional AI evaluations. Use these endpoints to
      submit recorded calls, receive asynchronous completion webhooks, fetch
      transcription status, and retrieve the final transcript with analysis.
  - name: Analytics
    description: >-
      Aggregated analytics across calls, conversations, sessions, evaluations,
      intents, appointments, and messages
  - name: Flows
    description: >-
      Studio automation flows — list, create, read, update, delete. A flow is a
      trigger step + N action steps that fire on real events (e.g. inbound call
      → post to Slack → create CRM contact). Flows live in draft until POST
      /deploy makes them live.
  - name: Flow Steps
    description: >-
      Add / update / delete steps inside a flow. The first step is always a
      trigger; subsequent steps are actions. Step IDs and their ordering
      (`step_number`) are managed by the server — adding or deleting a step
      automatically renumbers and rewrites `{{stepN.field}}` references in
      downstream steps.
  - name: Flow Catalog
    description: >-
      Read-only discovery of integrations and their capabilities. Lists apps,
      triggers, actions, OAuth connections, agents, and dynamic field options.
      The MCP server uses this to translate natural language ("post to Slack
      #general") into the IDs/keys the action config requires.
  - name: Flow Executions
    description: >-
      Execution history for a deployed flow — every real trigger event that
      fires produces one execution row with per-step
      request/response/duration/status.
  - name: Voice IVR & Guards
    description: >-
      Two related but distinct features that decide when an agent transfers a
      call or ends a conversation.


      WHAT THEY ARE:

      - ROUTING RULES (Voice-Activated IVR): customer-intent-driven transfers.
      When the customer ASKS for something (sales, support, manager), routing
      rules pick the right destination. This is the IVR replacement.

      - GUARD RULES (Guard & Hand Over): situation-driven transfers or
      call-ends. When the runtime detects a sensitive SITUATION (legal
      complaint, profanity, compliance violation, customer in distress), the
      guard fires regardless of what the customer asked for.


      WHEN TO USE WHICH:

      - Customer says 'I want to speak to a manager' -> ROUTING rule (intent:
      customer wants escalation).

      - Customer threatens legal action -> GUARD rule (situation:
      compliance/safety overrides whatever the customer was asking).

      - Customer asks for technical support -> ROUTING rule.

      - Customer becomes abusive -> GUARD rule (then_action: end_conversation or
      forward).

      - Rule of thumb: routing = 'where do they want to go?', guard = 'this
      conversation needs to stop or hand off NOW'.


      PRIORITY AND ORDERING:

      - Routing rules have a numeric `priority` field. Lower number = higher
      priority = evaluated first. Ties resolved by insertion order.

      - Guard rules ALWAYS take precedence over routing rules. If a guard fires,
      routing is bypassed.

      - If multiple guards could fire on the same utterance, only the first
      match wins.


      DETECTION MECHANICS (routing only):

      - detection_mode = exact: the customer must say `trigger_keyword`
      literally. Fast, narrow, language-sensitive.

      - detection_mode = intent: the runtime AI uses `ai_prompt` + `phrases` to
      classify intent semantically. Broader, multilingual, requires good
      ai_prompt wording.

      - detection_mode = both: runs exact first, falls back to intent.
      Recommended for production.


      REQUIRED FIELDS FOR THE AI TO PICK THE RULE:

      - Routing intent/both: `ai_prompt` + `phrases` (3-5 examples).

      - Routing exact: `trigger_keyword`.

      - Guard: `when_condition` + `example_phrases`.

      Without these, the runtime cannot classify utterances and the rule never
      fires.


      CRUD MODES:

      - PUT  /agents/{uuid}/routing-rules  or  /guard-rules  — REPLACE all rules
      in one call. Old rules are deleted first. Use for bulk imports or full
      re-syncs.

      - POST /agents/{uuid}/routing-rules  or  /guard-rules  — ADD one rule,
      leave others intact. Returns 201. Use for incremental builds.

      - PATCH /...{ruleUuid}  — partial UPDATE of one rule. Only sent keys are
      touched.

      - DELETE /...{ruleUuid} — remove one rule.

      Per-rule POST/PATCH/DELETE preserve other rules; PUT replaces everything.
  - name: PBX Extension Connectors
    description: >-
      Voice PBX & Extension Connectors — register a PBX extension against an AI
      voice agent. This is the PBX-side configuration only; it does not
      provision a SIP trunk. Use it when you want to connect a number you've
      purchased from us into your existing PBX extension. If you already have a
      SIP trunk from a provider, use the SIP Trunking endpoints directly
      instead.
  - name: Phone Numbers
    description: Manage phone number inventory, channel bindings, search, and rates
  - name: Contact Pipeline
    description: >-
      Pipeline stages classify where a contact is in your sales, support, or
      onboarding process. Use these endpoints to define the ordered stage list,
      move contacts between stages through contact updates, and keep inactive
      stages out of normal selection while preserving history.
  - name: Pools
    description: >-
      Contact pools — named buckets of contacts that one or more campaigns draw
      from. A pool's `type` (FIFO / LIFO / Parallel) controls dispatch order
      when a campaign is running.


      **Typical workflow (build a pool from scratch):**

      1. POST /api/v1/contacts — create the contacts you want to reach (or use
      existing UUIDs)

      2. POST /api/v1/pools — create a pool

      3. POST /api/v1/pools/{uuid}/contacts — bulk-add contacts by UUID

      4. (attach to campaign — see Campaigns tag)


      **Inspect / manage:**

      - GET /api/v1/pools/{uuid}/contacts — paginated list of pool members with
      status, retries, started_at

      - DELETE /api/v1/pools/{uuid}/contacts/{contact_uuid} — remove one contact
      and cancel only THAT contact's pending tasks (not their tasks in other
      pools)

      - POST /api/v1/pools/{uuid}/duplicate — clone pool config, optionally with
      all members


      **Side effect on a running campaign:** if you POST /pools/{uuid}/contacts
      to a pool already attached to an In Process campaign, tasks are
      auto-created for the new contacts in EVERY running campaign attached to
      that pool. Same call works for draft campaigns too — it just doesn't
      create tasks until publish.


      **Delete guard:** DELETE /api/v1/pools/{uuid} returns 409 if the pool is
      attached to a campaign in In Process or Importing status. Stop or detach
      first.
  - name: Rules
    description: >-
      Campaign contact rules — call cadence, retry intervals, working-hours
      window, and escalation policy. A rule defines HOW often and WHEN a
      campaign reaches a contact; the campaign defines WHO and WHAT.


      **Typical workflow:**

      1. POST /api/v1/rules — create a rule (call or text type)

      2. POST /api/v1/campaigns — create a campaign in Draft status

      3. PUT /api/v1/campaigns/{uuid}/rule — attach the rule (replaces any prior
      rule)

      4. (continue with pool attachment + publish — see Campaigns tag)


      **Type-aware behavior:**

      - type='call' rules honor retry_interval_minutes and end_time
      (working-hours window).

      - type='text' rules force one-shot semantics: max_total_calls=1,
      retry/end_time nulled. Used for SMS and WhatsApp campaigns.


      **Caveat:** changing a rule on a campaign that's already In Process does
      NOT rebuild already-scheduled tasks. New tasks created after the change
      pick up new values; old ones keep the old cadence. To force a hard reset:
      stop campaign → assign new rule → publish again.
  - name: Contact Tags
    description: >-
      Manage contact tags for your account. Each tag is identified by its
      `uuid`.
  - name: Timezone
    description: Timezones available for agent configuration.
  - name: Voice Library
    description: >-
      Catalog of voices available to agents and the speed options each voice
      supports.
  - name: WhatsApp Templates
    description: >-
      Manage WhatsApp message templates — Meta-approved messages used for
      outbound WhatsApp campaigns. All endpoints are scoped to the tenant: you
      can only act on linked WABAs (WhatsApp Business Accounts).


      **Typical workflow — pull existing templates:**

      1. GET /api/v1/whatsapp/wabas — discover WABAs linked to your tenant

      2. POST /api/v1/whatsapp/templates/sync — pull all templates Meta has for
      a WABA (one-time bootstrap)

      3. GET /api/v1/whatsapp/templates?waba_id=...&active_only=true — list
      APPROVED templates ready to use

      4. Use a template UUID with POST /api/v1/whatsapp/template (one-shot send)
      or in a campaign


      **Typical workflow — create a brand-new template with a media header:**

      1. POST /api/v1/whatsapp/templates/upload-media (multipart) — upload your
      image/video/document, receive a `handle`

      2. POST /api/v1/whatsapp/templates — submit with `components` including
      HEADER referencing the handle

      3. Wait — Meta approval is async, usually minutes. Status starts as
      PENDING.

      4. POST /api/v1/whatsapp/templates/{uuid}/sync — refresh status until
      APPROVED, REJECTED, or PAUSED

      5. Once APPROVED, use it in sends/campaigns


      **Component shape — quick reference:**

      - HEADER text:    { type:'HEADER', format:'TEXT', text:'Hi {{1}}',
      example:{header_text:['John']} }

      - HEADER image:   { type:'HEADER', format:'IMAGE',
      example:{header_handle:['<from upload-media>']} }

      - HEADER video/document: same as image with format=VIDEO or DOCUMENT

      - BODY:           { type:'BODY', text:'Order {{1}} ready',
      example:{body_text:[['12345']]} }   note nested array

      - FOOTER:         { type:'FOOTER', text:'Reply STOP to unsubscribe' }

      - BUTTONS group:  { type:'BUTTONS', buttons:[ ... ] } with up to 10
      buttons:
          QUICK_REPLY:  { type:'QUICK_REPLY', text:'Yes please' }
          URL:          { type:'URL', text:'Track', url:'https://example.com' }
          PHONE_NUMBER: { type:'PHONE_NUMBER', text:'Call', phone_number:'+1234567890' }
          COPY_CODE:    { type:'COPY_CODE', example:'WELCOME10' }

      **Tenant scoping:**

      - 403: WABA is not linked to your tenant (no matching WhatsappSetting row)

      - 404 (not 403): templates that belong to other tenants — surfaced as 'not
      found' to avoid info leak. Same convention for non-whatsapp template types
      and orphan rows.


      **How auth works:** the existence of a WhatsappSetting row in the tenant
      DB IS the ownership proof — multi-tenant DB scoping handles isolation. The
      Meta access token used for API calls is the platform-global
      config('whatsapp.access_token'), the same token that powers every other
      WhatsApp send in this codebase (replies, campaigns, one-shot template
      sends). If WhatsappSetting.access_token is populated, that takes
      precedence — but onboarding doesn't fill it today, so the platform token
      is what actually runs.
  - name: Agent Channel Bindings
    description: Agent Channel Bindings
  - name: Contact Blacklist
    description: Contact Blacklist
  - name: SIP Trunk
    description: SIP Trunk
paths:
  /api/v1/phone-numbers:
    post:
      tags:
        - Phone Numbers
      summary: Buy a phone number
      description: >-
        Purchases a number returned by the search endpoint. If the country/type
        requires compliance, include an address (when needed) and a list of
        requirement values — text answers and document IDs from
        /api/v1/phone-numbers/documents. Subject to a per-workspace cap on
        active numbers purchased via the API; when the cap is reached you
        receive HTTP 403 with `data.error = purchase_limit_reached` plus the
        actual `limit` and `current` count in the response body.
      operationId: purchasePhoneNumber
      requestBody:
        required: true
        content:
          application/json:
            schema:
              required:
                - number
                - country_code
                - type
              properties:
                number:
                  description: >-
                    The exact E.164 number to purchase, returned by `GET
                    /phone-numbers/search`. The endpoint refuses if the same
                    number already exists in your inventory or as an external
                    trunk.
                  type: string
                  example: '+390790080041'
                country_code:
                  description: >-
                    ISO 3166-1 alpha-2 country code the number belongs to. Used
                    to fetch regulatory requirements and as the default for the
                    address `country_code`.
                  type: string
                  example: IT
                type:
                  description: >-
                    Number category from the search result. Drives which
                    compliance requirements apply.
                  type: string
                  enum:
                    - local
                    - toll_free
                    - mobile
                    - national
                monthly_fee:
                  description: >-
                    Monthly fee value carried over from the search result.
                    Stored on the inventory row for billing display. The first
                    active number in your workspace is free regardless of this
                    value.
                  type: number
                  format: float
                capabilities:
                  description: >-
                    Capability flags object copied from the search result
                    (`voice`, `sms`, `mms`, etc.). Indicates which channels the
                    number supports. Optional — when omitted, channel
                    capabilities are unknown until the number is purchased.
                  type: object
                location:
                  description: >-
                    Optional human-friendly location label, e.g. `Sassari,
                    Sardegna`. Defaults to the country code if omitted.
                  type: string
                address:
                  description: >-
                    Compliance address. Required when the country/type
                    combination needs one (check `GET
                    /phone-numbers/search/requirements`). All fields are
                    individually optional — provide as many as the carrier
                    requires.
                  properties:
                    first_name:
                      description: >-
                        End-user first name. Required for personal-use numbers
                        in many EU countries.
                      type: string
                    last_name:
                      description: End-user last name.
                      type: string
                    business_name:
                      description: >-
                        Legal business name. Required instead of personal name
                        for business-use numbers.
                      type: string
                    phone_number:
                      description: >-
                        A contact phone number for the address holder (NOT the
                        number being purchased).
                      type: string
                    street_address:
                      description: Street + house number.
                      type: string
                    extended_address:
                      description: >-
                        Apartment, suite, building, etc. Optional second address
                        line.
                      type: string
                    locality:
                      description: City.
                      type: string
                    administrative_area:
                      description: State, province, or region.
                      type: string
                    postal_code:
                      description: Postal/ZIP code.
                      type: string
                    country_code:
                      description: >-
                        ISO 3166-1 alpha-2 country code for the address.
                        Defaults to the top-level `country_code`.
                      type: string
                      example: IT
                  type: object
                requirements:
                  description: >-
                    Compliance requirement values. One entry per requirement
                    listed in `GET /phone-numbers/search/requirements`. Each
                    entry identifies the requirement (by `key` slug or stable
                    `requirement_id`) and supplies the value (text answer or
                    uploaded document id).
                  type: array
                  items:
                    properties:
                      key:
                        description: >-
                          Slug of the requirement name (lowercase, non-alphanum
                          → `_`). Returned in the `key` field of
                          `/search/requirements`. Either `key` or
                          `requirement_id` is required per entry.
                        type: string
                        example: proof_of_address
                      requirement_id:
                        description: >-
                          Stable carrier ID for the requirement. Preferred over
                          `key` when available — survives requirement renames.
                        type: string
                        example: 9bcb8f00-c0c5-4ee1-9b75-ad1e87a2bd8b
                      value:
                        description: >-
                          Text answer for `textual` requirements (e.g. an ID
                          number). Either `value` or `document_id` is required
                          per entry.
                        type: string
                      document_id:
                        description: >-
                          Document ID returned by `POST
                          /phone-numbers/documents`. Use this for `document`
                          requirements.
                        type: string
                    type: object
              type: object
      responses:
        '201':
          description: Number purchased
          content:
            application/json:
              schema:
                properties:
                  success:
                    description: >-
                      Indicates whether the request completed successfully. True
                      for successful responses; false for documented error
                      responses.
                    type: boolean
                  data:
                    $ref: '#/components/schemas/PhoneNumberItem'
                type: object
        '403':
          description: Per-workspace API purchase limit reached
          content:
            application/json:
              schema:
                properties:
                  success:
                    description: Always false on a 403 response.
                    type: boolean
                    example: false
                  message:
                    description: >-
                      Human-readable message including the current count and the
                      cap.
                    type: string
                    example: >-
                      You already have 5 phone numbers, which is the maximum
                      allowed via the API (5). Release a number before
                      purchasing another.
                  data:
                    properties:
                      error:
                        description: Stable error code for programmatic handling.
                        type: string
                        example: purchase_limit_reached
                      limit:
                        description: The current cap value enforced by the server.
                        type: integer
                        example: 5
                      current:
                        description: >-
                          How many active phone-number rows the workspace
                          already has.
                        type: integer
                        example: 5
                    type: object
                type: object
        '422':
          description: Validation error or missing compliance fields
        '502':
          description: Purchase failed at the carrier
        '503':
          description: Purchase service unavailable
      security:
        - bearerAuth: []
components:
  schemas:
    PhoneNumberItem:
      description: >-
        A phone number connected to your workspace. Always returned by inventory
        and lookup endpoints. The shape is the same for purchased and external
        (trunk) numbers — fields that don't apply to externals come back as
        null.
      properties:
        phone_number_uuid:
          description: >-
            Stable identifier for purchased numbers. `null` for external trunks
            (they have no inventory record). Use this in URL path parameters
            such as `/phone-numbers/{uuid}`.
          type: string
          format: uuid
          example: 9bcb8f00-c0c5-4ee1-9b75-ad1e87a2bd8b
          nullable: true
        number:
          description: >-
            The phone number in E.164 format whenever possible (`+12084439178`).
            External trunks may be stored as raw digits (`12084439178`) — both
            forms are valid.
          type: string
          example: '+12084439178'
        country_code:
          description: >-
            ISO 3166-1 alpha-2 country code. Set when the row's `location` is
            exactly two letters (e.g. `US`); `null` otherwise. For freeform
            labels like `California` or `Sassari`, see the separate `location`
            field.
          type: string
          example: US
          nullable: true
        location:
          description: >-
            Freeform location label as stored on the row — could be a country
            code, city, region, or carrier-supplied descriptor. Use this when
            `country_code` is null.
          type: string
          example: Sassari, Sardegna
          nullable: true
        type:
          description: >-
            Number category. `local` = geographic local number, `toll_free` = no
            caller charge, `mobile` = mobile network, `national` = country-wide
            non-geographic. `null` for trunks where we don't have this metadata.
          type: string
          enum:
            - local
            - toll_free
            - mobile
            - national
          nullable: true
        is_external:
          description: >-
            True if the row is a registered trunk (BYO number) — bound to an
            agent via SIP/Setting tables but not in your purchased inventory.
            False if the number was bought through this platform.
          type: boolean
        source:
          description: >-
            Text version of `is_external` for clients that prefer enums over
            booleans. `purchased` = owned inventory (full lifecycle: compliance,
            billing, capabilities). `external` = registered SIP trunk / BYO line
            (no billing, no compliance state).
          type: string
          enum:
            - purchased
            - external
        status:
          description: >-
            Lifecycle status of the inventory row. `pending` = ordered but not
            yet activated by carrier. `active` = ready for use. `inactive` =
            paused. `deleted` = soft-deleted. `null` for external trunks.
          type: string
          enum:
            - active
            - pending
            - inactive
            - deleted
          nullable: true
        compliance:
          description: >-
            Regulatory compliance state. Present only for purchased numbers.
            `null` for external trunks.
          properties:
            status:
              description: >-
                `completed` = all required documents/answers accepted.
                `requirement_pending` = at least one regulatory requirement is
                still outstanding; the number cannot be used for outbound
                traffic until cleared.
              type: string
              enum:
                - completed
                - requirement_pending
            requirements:
              description: >-
                The remaining regulatory requirements (if any). Each entry has
                `name`, `type` (textual/document/address), and a human
                description. Empty when status is `completed`.
              type: array
              items:
                properties:
                  name:
                    description: >-
                      Human-readable requirement label, e.g. `End User First
                      Name`.
                    type: string
                  type:
                    description: >-
                      What the requirement expects: free text, an uploaded
                      document ID, or a structured address ID.
                    type: string
                    enum:
                      - textual
                      - document
                      - address
                  description:
                    description: Carrier-provided explanation of what to supply.
                    type: string
                    nullable: true
                type: object
          type: object
          nullable: true
        capabilities:
          description: >-
            What the number supports at the carrier level. Set at purchase time
            and immutable. `null` for external trunks (we don't probe their
            capabilities).
          properties:
            voice:
              description: Number can place/receive voice calls.
              type: boolean
            sms:
              description: Number can send/receive SMS.
              type: boolean
            mms:
              description: Number can send/receive MMS.
              type: boolean
            fax:
              description: Number can send/receive fax (rare).
              type: boolean
            emergency:
              description: Number can dial emergency services in its country.
              type: boolean
            local_calling:
              description: Outbound to numbers in the same country is local-rated.
              type: boolean
          type: object
          nullable: true
        channel_settings:
          description: >-
            Per-channel routing controls. Editable via `PATCH
            /phone-numbers/{uuid}`. `null` for external trunks (use the trunk
            endpoints instead).
          properties:
            voice:
              description: Outbound voice settings.
              properties:
                enabled:
                  description: Whether outbound voice is allowed on this number.
                  type: boolean
                channel_limit:
                  description: >-
                    Maximum concurrent outbound calls. `null` = no explicit cap
                    (uses provider default).
                  type: integer
                  nullable: true
                whitelisted_destinations:
                  description: >-
                    ISO 3166-1 alpha-2 destination country codes allowed for
                    outbound voice. Empty means restricted — calls only routable
                    to defaults configured at provision time.
                  type: array
                  items:
                    type: string
                    example: US
              type: object
            sms:
              description: Outbound SMS settings.
              properties:
                enabled:
                  description: Whether outbound SMS is allowed on this number.
                  type: boolean
                channel_limit:
                  description: >-
                    Maximum concurrent outbound SMS sends. `null` = no explicit
                    cap.
                  type: integer
                  nullable: true
                whitelisted_destinations:
                  description: >-
                    ISO 3166-1 alpha-2 destination country codes allowed for
                    outbound SMS.
                  type: array
                  items:
                    type: string
                    example: US
              type: object
            inbound:
              description: Inbound traffic settings (applies to both voice and SMS).
              properties:
                enabled:
                  description: Whether the number accepts incoming traffic.
                  type: boolean
                channel_limit:
                  description: Maximum concurrent inbound calls. `null` = no explicit cap.
                  type: integer
                  nullable: true
              type: object
          type: object
          nullable: true
        billing:
          description: >-
            Recurring cost block for purchased numbers. `null` for external
            trunks (you pay your own carrier).
          properties:
            monthly_fee:
              description: >-
                Recurring monthly fee charged to your wallet. Your first active
                number is free — `0.00` will be reflected for that one until
                it's released.
              type: number
              format: float
            currency:
              description: >-
                ISO 4217 currency code that monthly_fee is denominated in.
                Pulled from your workspace wallet (typically `EUR` or `USD`).
              type: string
              example: EUR
          type: object
          nullable: true
        bindings:
          description: >-
            Which agent answers traffic on which channel for this number. Always
            present (uses null agent fields if no binding). Bind/unbind via
            `/phone-numbers/{uuid}/bindings/{channel}` for purchased numbers, or
            the trunk endpoints for externals.
          properties:
            call:
              description: Voice call binding.
              properties:
                bound:
                  description: >-
                    True if an agent is currently assigned to call traffic on
                    this number.
                  type: boolean
                agent_uuid:
                  description: UUID of the bound agent. `null` if unbound.
                  type: string
                  nullable: true
                agent_name:
                  description: >-
                    Display name of the bound agent (`name` + `surname` joined).
                    `null` if unbound.
                  type: string
                  nullable: true
              type: object
            sms:
              description: SMS binding.
              properties:
                bound:
                  description: >-
                    True if an agent handles inbound/outbound SMS on this
                    number.
                  type: boolean
                agent_uuid:
                  type: string
                  nullable: true
                agent_name:
                  type: string
                  nullable: true
              type: object
            whatsapp:
              description: >-
                WhatsApp binding (works for both purchased numbers with WhatsApp
                Business and external WhatsApp Business lines).
              properties:
                bound:
                  description: True if an agent handles WhatsApp traffic on this number.
                  type: boolean
                agent_uuid:
                  type: string
                  nullable: true
                agent_name:
                  type: string
                  nullable: true
              type: object
          type: object
        purchased_at:
          description: >-
            ISO-8601 timestamp of when the number was purchased through the
            platform. `null` for external trunks.
          type: string
          format: date-time
          nullable: true
        updated_at:
          description: >-
            ISO-8601 timestamp of the last mutation to the inventory row
            (settings changes, status updates, etc.). `null` for external
            trunks.
          type: string
          format: date-time
          nullable: true
      type: object
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Use a Bearer token to access these API endpoints. Example: "Bearer
        {your-token}"

````