Numbers Online PBX API

Plain-text caller-id lookup for header-less PBX integrations (FreeSWITCH mod_cidlookup and similar)

Operations 2

GET /api/v1/cid/{number} Plain-text caller-id lookup #
GET /api/v1/cid Plain-text caller-id (zero-segment fallback) #

Documentation

Specifications

Other Resources

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/numbers-online:numbers-online-pbx-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

numbers-online-pbx-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Numbers Online Phone Intelligence PBX API
  description: Phone number parsing, validation, and inbound caller-intelligence as a supplementary signal.
  version: 1.0.0
  contact:
    name: Phone Numbers Online
    url: https://numbers.online
servers:
- url: https://numbers.online
  description: Production server
- url: http://localhost:3000
  description: Development server
tags:
- name: PBX
  description: Plain-text caller-id lookup for header-less PBX integrations (FreeSWITCH mod_cidlookup and similar)
paths:
  /api/v1/cid/{number}:
    get:
      tags:
      - PBX
      summary: Plain-text caller-id lookup
      description: 'Caller-name (CNAM) lookup that ALWAYS returns `text/plain` — every response, including auth, balance, and rate-limit failures, is plain text so a PBX can paste the body verbatim into a caller name without ever rendering a JSON error blob. Built for header-less integrations such as FreeSWITCH `mod_cidlookup`, which substitutes the raw inbound number into a URL and uses the response body as the caller name. The body is the resolved name (`ACME CORP`), the name prefixed with an operator-chosen risk tag when one is configured and the spam signal crosses the threshold (`Spam? ACME CORP`), or the literal sentinel `UNAVAILABLE` when there is no name, the number is unresolvable, the caller is tenant-suppressed, or auth/balance/rate-limit fails (the HTTP status code is still meaningful — `200` for an ordinary no-result, `401`/`402`/`429` for the failure cases). The number is resolved loosely: 10/11-digit national, `+`E.164, or `00`-prefixed international are all accepted (anonymous callers and alphanumeric SIP user-parts yield `UNAVAILABLE`). Billing is identical to /api/v1/lookup (`$0.004` on a fresh wholesale CNAM dip, `$0.002` otherwise; unresolvable and tenant-suppressed numbers are free). Requires an API key with the `lookup` use case. Fail-open: a slow or failing supplier yields `UNAVAILABLE`, never an error on the call path.'
      operationId: cidLookup
      security:
      - ApiKeyAuth: []
      - BearerAuth: []
      - CidQueryKeyAuth: []
      parameters:
      - name: number
        in: path
        required: true
        description: The inbound caller number as it arrived from the trunk — a bare national number (`2025550123`), 11-digit (`12025550123`), full E.164 (`+12025550123`), or its URL-encoded form. PBX clients substitute this token (e.g. mod_cidlookup's `${caller_id_number}`) with no normalization.
        schema:
          type: string
        example: '12025550123'
      - name: key
        in: query
        required: false
        description: 'API key as a query param. Intended for header-less integrations (e.g. FreeSWITCH `mod_cidlookup`) that cannot send an `Authorization`/`X-API-Key` header. Also accepted by the webhook adapters (`/api/v1/integrations/retell/inbound`, `/api/v1/integrations/vapi/tool`, `/api/v1/sbc/redirect`) for the same reason. The key can land in proxy/gateway access logs, so use a dedicated, rotated key. Prefer header auth (`Authorization: Bearer` / `X-API-Key`) wherever the client can send headers.'
        schema:
          type: string
        example: nol_YOUR_API_KEY
      - name: country
        in: query
        required: false
        description: Default country (ISO 3166-1 alpha-2) used to resolve bare national numbers that arrive without a country code. Defaults to `US`.
        schema:
          type: string
        example: US
      - name: spam_tag
        in: query
        required: false
        description: Operator-opt-in risk prefix. When set, a caller whose supplementary spam signal is at or above `spam_threshold` has the body returned prefixed with this text (e.g. `Spam? ACME CORP`, or the tag alone when no name is available). When absent, the risk signal NEVER alters the body — risk wording is strictly the operator's choice.
        schema:
          type: string
        example: Spam?
      - name: spam_threshold
        in: query
        required: false
        description: Spam-signal threshold (1–99, default 80) at or above which the `spam_tag` prefix is applied. Has no effect unless `spam_tag` is also set.
        schema:
          type: integer
          minimum: 1
          maximum: 99
          default: 80
        example: 80
      - name: max_cache_age
        in: query
        required: false
        description: 'Operator TTL control: maximum acceptable CNAM cache age in seconds. A cached value older than this triggers a fresh wholesale dip; `0` forces a fresh dip (billed at the `$0.004` rate).'
        schema:
          type: integer
          minimum: 0
        example: 300
      responses:
        '200':
          description: Plain-text caller name, an operator-tagged name, or the `UNAVAILABLE` sentinel (no name, unresolvable number, or tenant-suppressed caller). Always `text/plain`.
          headers:
            Cache-Control:
              description: Always `no-store` — the response is per-request and billed.
              schema:
                type: string
                example: no-store
          content:
            text/plain:
              schema:
                type: string
                example: ACME CORP
        '401':
          description: 'Authentication failed (missing or invalid key). Body is still plain text: `UNAVAILABLE`.'
          content:
            text/plain:
              schema:
                type: string
                example: UNAVAILABLE
        '402':
          description: 'Standard-tier prepaid balance is exhausted. Body is still plain text: `UNAVAILABLE`. Top up (POST /api/v1/account/topup) to resume.'
          content:
            text/plain:
              schema:
                type: string
                example: UNAVAILABLE
        '429':
          description: Per-key rate limit exceeded. Body is plain text `UNAVAILABLE`; a `Retry-After` header (seconds) is set.
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
          content:
            text/plain:
              schema:
                type: string
                example: UNAVAILABLE
  /api/v1/cid:
    get:
      tags:
      - PBX
      summary: Plain-text caller-id (zero-segment fallback)
      description: Zero-segment fallback for a PBX whose URL template failed to substitute the caller number (so the request arrives at `/api/v1/cid` with no number). Always returns `text/plain` `UNAVAILABLE` with HTTP 200, so a broken template never renders a 404 page as the caller name. Takes no key and runs no lookup — purely the safe default for `mod_cidlookup` and similar header-less clients still being wired up.
      operationId: cidLookupFallback
      security: []
      responses:
        '200':
          description: Always the plain-text sentinel `UNAVAILABLE`.
          headers:
            Cache-Control:
              description: Always `no-store`.
              schema:
                type: string
                example: no-store
          content:
            text/plain:
              schema:
                type: string
                example: UNAVAILABLE
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: API key for authentication
    BearerAuth:
      type: http
      scheme: bearer
      description: Bearer token authentication
    CidQueryKeyAuth:
      type: apiKey
      in: query
      name: key
      description: API key in the `?key=` query param. Accepted by the header-less PBX endpoint GET /api/v1/cid/{number} and by the webhook adapters POST /api/v1/integrations/retell/inbound, POST /api/v1/integrations/vapi/tool, and POST /api/v1/sbc/redirect, whose upstream platforms set only a static webhook URL and cannot send an Authorization/X-API-Key header. The key can leak into access logs — use a dedicated, rotated key, and prefer header auth wherever the client supports it.