# Purchase a phone number (/docs/api-reference/phone-numbers/purchasePhoneNumber)

> Buy a phone number from the OmniDimension number shop. The monthly rental comes out of your wallet and the number is added to your account, ready to attach to an agent.

**POST** `/phone_number/purchase`

Buy a phone number from the OmniDimension number shop. The monthly
rental comes out of your wallet and the number is added to your
account, ready to attach to an agent.

```yaml
operationId: purchasePhoneNumber
parameters:
  - name: Idempotency-Key
    in: header
    required: false
    description: |
      Your own unique key for this purchase, for example a
      fresh UUID. Strongly recommended: it is what makes a
      retry safe.
    schema:
      type: string
    example: 9f2c1d40-7a53-4b8e-9b7a-1c2d3e4f5a6b
requestBody:
  required: true
  content:
    application/json:
      schema:
        type: object
        required:
          - region
          - phone_number
        properties:
          region:
            type: string
            enum:
              - IN
              - US
            description: Region the number belongs to.
          phone_number:
            type: string
            description: The number to buy, as returned by the search operation.
            example: '+15551234567'
          user_id:
            type: integer
            description: 'Reseller accounts only: the client to act on. Omit it to act on your own account.'
      example:
        region: US
        phone_number: '+15551234567'
responses:
  '200':
    description: |
      The number was purchased, or the same `Idempotency-Key`
      was replayed and the original order is returned.
    content:
      application/json:
        schema:
          type: object
          properties:
            success:
              type: boolean
            replayed:
              type: boolean
              description: Present only when this key was already used. The order was not charged again.
            order_id:
              type: integer
            phone_number:
              type: string
            amount:
              type: number
              description: Amount charged, in USD.
            new_balance:
              type: number
              description: The owning account's balance after the charge. Not present on a replay.
            status:
              type: string
              description: Always `completed` on a successful purchase.
              enum:
                - completed
        examples:
          purchased:
            summary: purchased
            value:
              success: true
              order_id: 5678
              phone_number: '+15551234567'
              amount: 5
              new_balance: 120.5
              status: completed
          replayed:
            summary: replayed
            value:
              success: true
              replayed: true
              order_id: 5678
              phone_number: '+15551234567'
              amount: 5
              status: completed
  '400':
    description: A required field is missing, or `phone_number` is not valid.
    content:
      application/json:
        schema:
          type: object
          properties:
            error:
              type: string
              description: Machine-readable error code.
            error_description:
              type: string
              description: Human-readable explanation.
        example:
          error: invalid_request
          error_description: Invalid phone number format.
  '401':
    description: Missing or invalid API key.
  '402':
    description: The client does not have enough balance for this purchase.
    content:
      application/json:
        schema:
          type: object
          properties:
            error:
              type: string
              description: Machine-readable error code.
            error_description:
              type: string
              description: Human-readable explanation.
        example:
          error: insufficient_balance
          error_description: Insufficient balance.
  '403':
    description: |
      Phone number access is switched off for the account buying
      (`feature_disabled`), a `user_id` was sent by a key that is not a
      reseller admin, or the named client's account is currently
      unavailable (`forbidden`).
    content:
      application/json:
        schema:
          type: object
          properties:
            error:
              type: string
              description: Machine-readable error code.
            error_description:
              type: string
              description: Human-readable explanation.
        example:
          error: feature_disabled
          error_description: Phone number access is disabled for this user.
  '404':
    description: |
      The `user_id` did not name one of your clients (`not_found`),
      or numbers are not available for this region (`not_available`).
    content:
      application/json:
        schema:
          type: object
          properties:
            error:
              type: string
              description: Machine-readable error code.
            error_description:
              type: string
              description: Human-readable explanation.
        example:
          error: not_found
          error_description: Child user not found.
  '409':
    description: |
      The purchase was refused before anything was charged:
      identity verification is not complete (`kyc_incomplete`),
      an earlier purchase is still running (`in_progress`), or the
      number was taken by someone else (`number_unavailable`).
    content:
      application/json:
        schema:
          type: object
          properties:
            error:
              type: string
              description: Machine-readable error code.
            error_description:
              type: string
              description: Human-readable explanation.
        example:
          error: kyc_incomplete
          error_description: Complete identity verification for this region first.
  '422':
    description: The purchase could not be completed.
    content:
      application/json:
        schema:
          type: object
          properties:
            error:
              type: string
              description: Machine-readable error code.
            error_description:
              type: string
              description: Human-readable explanation.
        example:
          error: purchase_failed
          error_description: The purchase could not be completed. Please try again or contact support.
  '500':
    description: Unexpected server error.
    content:
      application/json:
        schema:
          allOf:
            - type: object
              properties:
                error:
                  type: string
                  description: Machine-readable error code.
                error_description:
                  type: string
                  description: Human-readable explanation.
            - type: object
              properties:
                ref:
                  type: string
                  description: Reference to quote to support.
        example:
          error: server_error
          error_description: >-
            Something went wrong on our side. Please try again shortly, or contact support with
            reference a1b2c3d4e5f6.
          ref: a1b2c3d4e5f6
```

**curl**

```bash
curl -X POST "https://omnidim.io/api/v1/phone_number/purchase" \
  -H "Authorization: Bearer $OMNIDIM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "region": "US",
  "phone_number": "+15551234567"
}'
```

## Retrying safely [#retrying-safely]

A phone number can only be sold once, so this endpoint cannot charge twice for
the same number, with or without a key. The `Idempotency-Key` header is for
recovering a **lost response**, not for preventing a double sale.

Send a fresh UUID with each purchase. If your request times out, retry with the
same key and you get your original order back with `replayed: true` instead of
guessing whether it went through, or `409 in_progress` if it is still running.

Reusing a key from a different purchase returns that first order. It is not
validated against your new request body, so use a fresh key each time.

## Before you can buy [#before-you-can-buy]

Some regions require the account to be identity-verified first. India is one,
and the check is an Aadhaar eKYC, so it completes in minutes. Verification done
in the dashboard counts: it is the same gate either way.

The whole flow, end to end, is in
[Buy a number over the API](/docs/buy-a-number-api).