---
title: "Buy a number"
description: "Trillet OEM API: Buys a number for the tenant, billed to your partner account at the standard Trillet number price."
openapi: /public/openapi/trillet-oem.yaml POST /partner/v1/tenants/{tenantId}/numbers
lastUpdated: "2026-10-28"
---

> **For AI agents:** the complete documentation index is at [llms.txt](https://docs.trillet.ai/llms.txt). Append `.md` to any page URL for its markdown version.

`POST https://api.trillet.ai/partner/v1/tenants/{tenantId}/numbers`

Buys a number for the tenant, billed to your partner account at the standard Trillet number
price. The first month is charged when you buy, then the number renews monthly.
Find numbers first with `GET /v1/api/twilio/available-numbers` and the tenant ID in
`x-workspace-id`. Needs `numbers:write`. `Idempotency-Key` is required.

## Authentication

- `partnerKey` — http bearer (tpk_live_...)

## Header parameters

- `Idempotency-Key` (string, required) — 1 to 255 printable ASCII characters, no spaces. A retry with the same key and request returns the stored response for 24 hours instead of running again.

## Request body

- Content type: `application/json`
  - request body (object)
    - `phoneNumber` (string, required) — E.164 format.
    - `country` (string, required) — Two-letter country code.
    - `type` (string, one of: local, mobile, default: "local")
    - `addressSid` (string) — Regulatory address, for countries that need one.
    - `bundleSid` (string) — Regulatory bundle, for countries that need one.

## Response 201

The number.
  - response (object)
    - `object` (string, required)
    - `id` (string, required) — Use it as `phoneNumberId` when binding the number to an agent.
    - `tenantId` (string, required)
    - `phoneNumber` (string, required) — E.164 format.
    - `provider` (string | null)
    - `type` (string | null)
    - `external` (boolean, required) — `true` for numbers you registered yourself.
    - `status` (string | null)
    - `agentId` (string | null)
    - `callFlowId` (string | null)
    - `billing` — Present for numbers bought through Trillet OEM, `null` for your own numbers.
      - (oneOf)
        - value (null)
        - value (object)
          - `monthlyPrice` (number | null) — Monthly price in USD.
          - `nextChargeAt` (string | null, date-time)
          - `status` (string, one of: active, past_due)
    - `createdAt` (string | null, date-time)

## Response 400

`invalid_request`, or `number_purchase_failed` when the carrier refused the purchase.
  - response (object)
    - `error` (object, required)
      - `type` (string, required, one of: invalid_request_error, authentication_error, permission_error, conflict_error, rate_limit_error, api_error, idempotency_error)
      - `code` (string, required) — A stable code. Handle errors by `code`, not by `message`.
      - `message` (string, required)
      - `param` (string) — The request field the error is about, when there is one.
      - `requestId` (string | null) — Include it when you contact support. Not present on idempotency errors.

## Response 401

The partner key is missing, malformed, unknown or revoked (`partner_key_required`, `invalid_api_key`, `partner_not_enabled`).
  - response (object)
    - `error` (object, required)
      - `type` (string, required, one of: invalid_request_error, authentication_error, permission_error, conflict_error, rate_limit_error, api_error, idempotency_error)
      - `code` (string, required) — A stable code. Handle errors by `code`, not by `message`.
      - `message` (string, required)
      - `param` (string) — The request field the error is about, when there is one.
      - `requestId` (string | null) — Include it when you contact support. Not present on idempotency errors.

## Response 402

`insufficient_funds`: your account cannot pay for the first month, or a spend cap has been reached.
  - response (object)
    - `error` (object, required)
      - `type` (string, required, one of: invalid_request_error, authentication_error, permission_error, conflict_error, rate_limit_error, api_error, idempotency_error)
      - `code` (string, required) — A stable code. Handle errors by `code`, not by `message`.
      - `message` (string, required)
      - `param` (string) — The request field the error is about, when there is one.
      - `requestId` (string | null) — Include it when you contact support. Not present on idempotency errors.

## Response 403

`missing_scope`, or `key_restricted` on webhook endpoint routes.
  - response (object)
    - `error` (object, required)
      - `type` (string, required, one of: invalid_request_error, authentication_error, permission_error, conflict_error, rate_limit_error, api_error, idempotency_error)
      - `code` (string, required) — A stable code. Handle errors by `code`, not by `message`.
      - `message` (string, required)
      - `param` (string) — The request field the error is about, when there is one.
      - `requestId` (string | null) — Include it when you contact support. Not present on idempotency errors.

## Response 404

Not found, or not yours. For example `tenant_not_found`.
  - response (object)
    - `error` (object, required)
      - `type` (string, required, one of: invalid_request_error, authentication_error, permission_error, conflict_error, rate_limit_error, api_error, idempotency_error)
      - `code` (string, required) — A stable code. Handle errors by `code`, not by `message`.
      - `message` (string, required)
      - `param` (string) — The request field the error is about, when there is one.
      - `requestId` (string | null) — Include it when you contact support. Not present on idempotency errors.

## Response 409

`tenant_suspended`, or an idempotency conflict.
  - response (object)
    - `error` (object, required)
      - `type` (string, required, one of: invalid_request_error, authentication_error, permission_error, conflict_error, rate_limit_error, api_error, idempotency_error)
      - `code` (string, required) — A stable code. Handle errors by `code`, not by `message`.
      - `message` (string, required)
      - `param` (string) — The request field the error is about, when there is one.
      - `requestId` (string | null) — Include it when you contact support. Not present on idempotency errors.

## Response 422

`idempotency_key_reused`: the same `Idempotency-Key` was sent with a different request.
  - response (object)
    - `error` (object, required)
      - `type` (string, required, one of: invalid_request_error, authentication_error, permission_error, conflict_error, rate_limit_error, api_error, idempotency_error)
      - `code` (string, required) — A stable code. Handle errors by `code`, not by `message`.
      - `message` (string, required)
      - `param` (string) — The request field the error is about, when there is one.
      - `requestId` (string | null) — Include it when you contact support. Not present on idempotency errors.


---

📦 **OpenAPI specs:** Every OpenAPI specification referenced by this documentation is available as a single download — https://docs.trillet.ai/api-specs.zip
