Business Numbers

A business number is a customer-facing phone number on your Phone.inc account — the one you'd publish on a website or business card. Every call and voicemail belongs to exactly one business number. Beyond listing them, you can retrieve the full settings (routing, business hours) and update them through the API.

The business number model

Each business number has a stable public id, the human label your team uses to identify it (name), the underlying phone number, and its full routing configuration.

Properties

  • Name
    id
    Type
    string
    Description

    Unique identifier for the business number.

  • Name
    name
    Type
    string
    Description

    The label your team set for this number, like Sales or Support. ASCII letters, numbers, spaces, and -_~!.+ only, up to 128 characters (no accented characters).

  • Name
    number
    Type
    string
    Description

    The phone number in E.164 format, e.g. +14155551234.

  • Name
    number_formatted
    Type
    string
    Description

    The same number formatted for display, e.g. +1 415-555-1234.

  • Name
    timezone
    Type
    string
    Description

    IANA timezone for the business number, e.g. Copenhagen or London.

  • Name
    language
    Type
    string
    Description

    Language code used for automated messages, e.g. da or en.

  • Name
    recording_enabled
    Type
    boolean
    Description

    Whether calls to this number are recorded.

  • Name
    incoming_call_config
    Type
    object
    Description

    The routing configuration for incoming calls. Contains a type field plus type-specific attributes.

  • Name
    outside_business_hours_config
    Type
    object | null
    Description

    The routing configuration used outside business hours, or null if not set (falls back to incoming call config). Newly created numbers start with a default VoicemailConfig here, greeting callers in the number's language; numbers created before this default may still be null.

  • Name
    no_answer_config
    Type
    object | null
    Description

    The routing configuration that runs when a call is transferred to employees but nobody answers within the ring timer, or null if no fallback is set. Same shape as the other two configs.

  • Name
    no_answer_timeout_secs
    Type
    integer | null
    Description

    How long a caller waits for an available employee before the no_answer_config takes over. null (or 0) means Off: the caller waits until someone answers or they hang up. Allowed values: 15, 30, 60, 300, 600, 1200, 1800, 2700, 3600. Every employee-transfer step queues the same way (in-hours, outside hours, menu branches, and no-answer fallbacks that transfer to employees). Only available employees are rung; callers wait in order. Voicemail and reject after hours never enqueue.

  • Name
    wait_audio
    Type
    string
    Description

    What the caller hears while waiting for an employee. ringtone (default, Nordic ringback) or music. Number-level, so a menu that transfers uses the same sound.

  • Name
    registration_status
    Type
    string
    Description

    Registration status of the business identity behind the number. One of not_required, pending, submitted, approved, rejected, or failed. Where a country regulates the number, we register it to your company's business identity and address, and it moves from pending to submitted to approved. not_required means no registration applies — usually because the number's country does not ask for one, in which case our carrier will not accept a registration even if we offer it. Numbers that did not come from us also report not_required. rejected means the carrier reviewed the registration and turned it down. failed means we could not submit it at all, usually because the company details we hold are incomplete. Both leave the number reachable but unregistered, and both need someone to act — get in touch if a number stays in either state.

  • Name
    registration_due_at
    Type
    string | null
    Description

    ISO 8601 timestamp indicating when the end-user registration must be completed for this number, or null if no registration is required. The number remains active during this window.

  • Name
    business_hours
    Type
    array
    Description

    Array of 7 objects (one per weekday) defining the opening schedule.

Call flow config types

All three routing slots — incoming_call_config, outside_business_hours_config, and no_answer_config — share the same set of config types:

TypeFields
WelcomeTransferConfigwelcome (string), employee_ids (non-empty array of strings)
TransferConfigemployee_ids (non-empty array of strings)
RejectConfigmessage (string)
VoicemailConfiggreeting (string)
PhoneMenuConfigwelcome (string), menu_options (non-empty array)

TransferConfig transfers the call to the chosen employees without playing a welcome message — it's WelcomeTransferConfig minus the greeting.

employee_ids must contain at least one employee. An empty array is rejected with a 422 validation error.

Phone menu options

PhoneMenuConfig plays its welcome greeting, then waits for the caller to press a single digit. Each entry in menu_options maps one digit to an action:

FieldTypeDescription
digitstringA single key, "1" through "9" only ("0" is rejected). Must be unique within the menu.
action_typestringWhat pressing the digit does (see below).
promptstringMessage played before the action runs. Required when action_type is WelcomeTransferConfig, VoicemailConfig, or PlayMessageConfig.
employee_idsarray of stringsTransfer targets. Required (non-empty) for TransferConfig and WelcomeTransferConfig.

action_type is one of:

action_typeWhat happens when the caller presses the digit
TransferConfigTransfer straight to employee_ids.
WelcomeTransferConfigPlay prompt, then transfer to employee_ids.
VoicemailConfigPlay prompt, then record a voicemail.
PlayMessageConfigPlay prompt, then hang up.

A menu needs at least one option, and every option's digit must be unique — duplicates or an empty menu_options array are rejected with a 422. On read, the response echoes each option's digit, action_type, prompt (when set), prompt_audio_url (generated audio), and employee_ids (resolved to public ids).

On read, every config that plays spoken text also returns the URL of its generated audio (or null while generation is pending): welcome_audio_url on WelcomeTransferConfig and PhoneMenuConfig, message_audio_url on RejectConfig, and greeting_audio_url on VoicemailConfig. Audio regenerates automatically whenever the text changes. To hear a text before saving it, use voice previews.

Send { "type": null } to clear the outside_business_hours_config or no_answer_config slot entirely. The incoming_call_config slot can't be cleared.


GET/v1/business_numbers

List all business numbers

Returns every business number on the authenticated employee's company. There's no pagination — companies have a small, finite set of business numbers, so the response is a single array.

The list endpoint returns a lean response (id, name, number, number_formatted). Use the retrieve endpoint for full settings including routing config and business hours.

Request

GET
/v1/business_numbers
curl https://app.phone.inc/api/v1/business_numbers \
  -H "X-Api-Key: $PHONE_INC_API_KEY"

Response

{
  "main_numbers": [
    {
      "id": "0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01",
      "name": "Sales",
      "number": "+14155551234",
      "number_formatted": "+1 415-555-1234"
    },
    {
      "id": "0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c02",
      "name": "Support",
      "number": "+14155555678",
      "number_formatted": "+1 415-555-5678"
    }
  ]
}

GET/v1/business_numbers/:id

Retrieve a business number

Returns the full settings for a single business number, including its incoming call config, outside-hours config, and weekly business hours schedule.

Request

GET
/v1/business_numbers/:id
curl https://app.phone.inc/api/v1/business_numbers/0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01 \
  -H "X-Api-Key: $PHONE_INC_API_KEY"

Response

{
  "id": "0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01",
  "name": "Sales",
  "number": "+14155551234",
  "number_formatted": "+1 415-555-1234",
  "timezone": "Copenhagen",
  "language": "da",
  "recording_enabled": false,
  "incoming_call_config": {
    "type": "PhoneMenuConfig",
    "welcome": "Press 1 for sales, 2 to leave a message",
    "welcome_audio_url": "https://app.phone.inc/rails/active_storage/blobs/redirect/...",
    "menu_options": [
      {
        "id": 42,
        "digit": "1",
        "action_type": "TransferConfig",
        "prompt": null,
        "prompt_audio_url": null,
        "employee_ids": ["019daef1-085e-7000-aaaa-000000000001"]
      },
      {
        "id": 43,
        "digit": "2",
        "action_type": "VoicemailConfig",
        "prompt": "Leave a message after the tone",
        "prompt_audio_url": "https://app.phone.inc/rails/active_storage/blobs/redirect/...",
        "employee_ids": []
      }
    ]
  },
  "outside_business_hours_config": {
    "type": "RejectConfig",
    "message": "We are closed, please call back tomorrow."
  },
  "no_answer_config": {
    "type": "VoicemailConfig",
    "greeting": "Sorry we missed you — leave a message after the tone."
  },
  "no_answer_timeout_secs": 30,
  "wait_audio": "ringtone",
  "registration_status": "approved",
  "registration_due_at": null,
  "business_hours": [
    { "day_of_week": 0, "day_name": "Monday", "open": true, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 1, "day_name": "Tuesday", "open": true, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 2, "day_name": "Wednesday", "open": true, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 3, "day_name": "Thursday", "open": true, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 4, "day_name": "Friday", "open": true, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 5, "day_name": "Saturday", "open": false, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 6, "day_name": "Sunday", "open": false, "opening_at": "09:00", "closing_at": "17:00" }
  ]
}

PATCH/v1/business_numbers/:id

Update a business number

Updates the scalar fields on a business number. Use the dedicated config endpoints below to change call routing or business hours.

Accepted fields

  • Name
    name
    Type
    string
    Description

    The display label for this number. ASCII letters, numbers, spaces, and -_~!.+ only, up to 128 characters.

  • Name
    timezone
    Type
    string
    Description

    IANA timezone identifier, e.g. Copenhagen, London, New_York.

  • Name
    language
    Type
    string
    Description

    Language code for automated messages: da, en, etc.

  • Name
    recording_enabled
    Type
    boolean
    Description

    Whether to record calls on this number.

Request

PATCH
/v1/business_numbers/:id
curl -X PATCH https://app.phone.inc/api/v1/business_numbers/0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01 \
  -H "X-Api-Key: $PHONE_INC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Sales Hotline", "timezone": "London"}'

Response

{
  "id": "0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01",
  "name": "Sales Hotline",
  "number": "+14155551234",
  "number_formatted": "+1 415-555-1234",
  "timezone": "London",
  "language": "da",
  "recording_enabled": false,
  "incoming_call_config": { "..." },
  "outside_business_hours_config": null,
  "no_answer_config": null,
  "no_answer_timeout_secs": null,
  "business_hours": [ "..." ]
}

PUT/v1/business_numbers/:id/incoming_call_config

Replace incoming call config

Replaces the routing configuration used when a call comes in during business hours. Send the desired type and its required fields. The full business number (with updated config) is returned.

Required fields by type

TypeFields
WelcomeTransferConfigwelcome, employee_ids (at least one id)
TransferConfigemployee_ids (at least one id)
RejectConfigmessage
VoicemailConfiggreeting
PhoneMenuConfigwelcome, menu_options (at least one option)

Request

PUT
/v1/business_numbers/:id/incoming_call_config
curl -X PUT https://app.phone.inc/api/v1/business_numbers/0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01/incoming_call_config \
  -H "X-Api-Key: $PHONE_INC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "WelcomeTransferConfig",
    "welcome": "Thanks for calling",
    "employee_ids": ["019daef1-085e-7000-aaaa-000000000001", "019daef1-085e-7000-aaaa-000000000002"]
  }'

Response

{
  "id": "0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01",
  "name": "Sales",
  "number": "+14155551234",
  "number_formatted": "+1 415-555-1234",
  "timezone": "Copenhagen",
  "language": "da",
  "recording_enabled": false,
  "incoming_call_config": {
    "type": "WelcomeTransferConfig",
    "welcome": "Thanks for calling",
    "employee_ids": ["019daef1-085e-7000-aaaa-000000000001", "019daef1-085e-7000-aaaa-000000000002"]
  },
  "outside_business_hours_config": null,
  "no_answer_config": null,
  "no_answer_timeout_secs": null,
  "business_hours": [ "..." ]
}

To set a phone menu instead, send type: "PhoneMenuConfig" with a menu_options array:

Phone menu example

PUT
/v1/business_numbers/:id/incoming_call_config
curl -X PUT https://app.phone.inc/api/v1/business_numbers/0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01/incoming_call_config \
  -H "X-Api-Key: $PHONE_INC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "PhoneMenuConfig",
    "welcome": "Press 1 for sales, 2 to leave a message",
    "menu_options": [
      { "digit": "1", "action_type": "TransferConfig", "employee_ids": ["019daef1-085e-7000-aaaa-000000000001"] },
      { "digit": "2", "action_type": "VoicemailConfig", "prompt": "Leave a message after the tone" }
    ]
  }'

Response

{
  "id": "0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01",
  "name": "Sales",
  "number": "+14155551234",
  "number_formatted": "+1 415-555-1234",
  "timezone": "Copenhagen",
  "language": "da",
  "recording_enabled": false,
  "incoming_call_config": {
    "type": "PhoneMenuConfig",
    "welcome": "Press 1 for sales, 2 to leave a message",
    "welcome_audio_url": "https://app.phone.inc/rails/active_storage/blobs/redirect/...",
    "menu_options": [
      {
        "id": 42,
        "digit": "1",
        "action_type": "TransferConfig",
        "prompt": null,
        "prompt_audio_url": null,
        "employee_ids": ["019daef1-085e-7000-aaaa-000000000001"]
      },
      {
        "id": 43,
        "digit": "2",
        "action_type": "VoicemailConfig",
        "prompt": "Leave a message after the tone",
        "prompt_audio_url": "https://app.phone.inc/rails/active_storage/blobs/redirect/...",
        "employee_ids": []
      }
    ]
  },
  "outside_business_hours_config": null,
  "no_answer_config": null,
  "no_answer_timeout_secs": null,
  "business_hours": [ "..." ]
}

PUT/v1/business_numbers/:id/outside_business_hours_config

Replace outside-hours config

Replaces the routing configuration used when a call comes in outside business hours. You can also update the business hours schedule in the same request by including the business_hours array.

Send { "type": null } to clear the outside-hours config entirely — calls will fall through to the regular incoming call config.

Required fields by type

TypeFields
RejectConfigmessage
WelcomeTransferConfigwelcome, employee_ids (at least one id)
TransferConfigemployee_ids (at least one id)
VoicemailConfiggreeting
PhoneMenuConfigwelcome, menu_options (at least one option)

Business hours object

  • Name
    day_of_week
    Type
    integer
    Description

    Day index: 0 = Monday, 6 = Sunday.

  • Name
    open
    Type
    boolean
    Description

    Whether the line is open on this day.

  • Name
    opening_at
    Type
    string
    Description

    Opening time in HH:MM format (24-hour).

  • Name
    closing_at
    Type
    string
    Description

    Closing time in HH:MM format. Use 24:00 for end of day.

Request

PUT
/v1/business_numbers/:id/outside_business_hours_config
curl -X PUT https://app.phone.inc/api/v1/business_numbers/0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01/outside_business_hours_config \
  -H "X-Api-Key: $PHONE_INC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "RejectConfig",
    "message": "We are closed, please call back tomorrow.",
    "business_hours": [
      { "day_of_week": 0, "open": true, "opening_at": "09:00", "closing_at": "17:00" },
      { "day_of_week": 1, "open": true, "opening_at": "09:00", "closing_at": "17:00" },
      { "day_of_week": 2, "open": true, "opening_at": "09:00", "closing_at": "17:00" },
      { "day_of_week": 3, "open": true, "opening_at": "09:00", "closing_at": "17:00" },
      { "day_of_week": 4, "open": true, "opening_at": "09:00", "closing_at": "17:00" },
      { "day_of_week": 5, "open": false, "opening_at": "09:00", "closing_at": "17:00" },
      { "day_of_week": 6, "open": false, "opening_at": "09:00", "closing_at": "17:00" }
    ]
  }'

Response

{
  "id": "0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01",
  "name": "Sales",
  "number": "+14155551234",
  "number_formatted": "+1 415-555-1234",
  "timezone": "Copenhagen",
  "language": "da",
  "recording_enabled": false,
  "incoming_call_config": { "..." },
  "outside_business_hours_config": {
    "type": "RejectConfig",
    "message": "We are closed, please call back tomorrow."
  },
  "no_answer_config": null,
  "no_answer_timeout_secs": null,
  "business_hours": [
    { "day_of_week": 0, "day_name": "Monday", "open": true, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 1, "day_name": "Tuesday", "open": true, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 2, "day_name": "Wednesday", "open": true, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 3, "day_name": "Thursday", "open": true, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 4, "day_name": "Friday", "open": true, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 5, "day_name": "Saturday", "open": false, "opening_at": "09:00", "closing_at": "17:00" },
    { "day_of_week": 6, "day_name": "Sunday", "open": false, "opening_at": "09:00", "closing_at": "17:00" }
  ]
}

PUT/v1/business_numbers/:id/no_answer_config

Replace no-answer config

Sets the flow that runs when a call is transferred to employees but nobody answers within the ring timer. Send the desired type, its required fields, and timeout_secs to arm the timer.

timeout_secs controls both the ring duration and whether the feature is on. Pass 15, 30, 60, 300, 600, 1200, 1800, 2700, or 3600. Send "", 0, or null to turn it off — calls then ring until they end naturally, exactly as before. Any other value is rejected with a 422.

Send { "type": null } to clear the no-answer flow.

Don't put employees in this flow's WelcomeTransferConfig or TransferConfig and expect another timeout — the no-answer transfer rings without a timer, so it never loops back into itself.

Required fields by type

TypeFields
WelcomeTransferConfigwelcome, employee_ids (at least one id)
TransferConfigemployee_ids (at least one id)
RejectConfigmessage
VoicemailConfiggreeting
PhoneMenuConfigwelcome, menu_options (at least one option)

Accepted fields

  • Name
    type
    Type
    string | null
    Description

    One of the call flow config types, or null to clear the slot.

  • Name
    timeout_secs
    Type
    integer | null
    Description

    Ring timer in seconds: 15, 30, 60, 300, 600, 1200, 1800, 2700, or 3600. 0, null, or a blank string ("", coerced to null server-side) turns the no-answer flow off.

Request

PUT
/v1/business_numbers/:id/no_answer_config
curl -X PUT https://app.phone.inc/api/v1/business_numbers/0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01/no_answer_config \
  -H "X-Api-Key: $PHONE_INC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "VoicemailConfig",
    "greeting": "Sorry we missed you — leave a message after the tone.",
    "timeout_secs": 30
  }'

Response

{
  "id": "0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01",
  "name": "Sales",
  "number": "+14155551234",
  "number_formatted": "+1 415-555-1234",
  "timezone": "Copenhagen",
  "language": "da",
  "recording_enabled": false,
  "incoming_call_config": { "..." },
  "outside_business_hours_config": null,
  "no_answer_config": {
    "type": "VoicemailConfig",
    "greeting": "Sorry we missed you — leave a message after the tone."
  },
  "no_answer_timeout_secs": 30,
  "business_hours": [ "..." ]
}

POST/v1/business_numbers/:id/voice_previews

Generate a voice preview

Generates a text-to-speech preview of text in the number's voice and language, so you can play a greeting before saving it. Returns a playable audio_url and the preview's signed id.

Previews are throwaway: saving a flow regenerates audio from the final text server-side, so you never have to send the preview back. Unused previews are cleaned up automatically.

Rate limited to 30 previews per minute per company. Exceeding it returns a 429.

Required fields

  • Name
    kind
    Type
    string
    Description

    Which field the text belongs to: welcome, greeting, message, or prompt. Anything else is rejected with a 422 and code invalid_kind.

  • Name
    text
    Type
    string
    Description

    The text to speak. Blank text is rejected with a 422 and code blank_text.

Errors

Voice generation depends on an upstream synthesis service. Failures there (timeouts, rate limits, rejected text, missing configuration) raise and return 500, which Sentry captures. Retrying after a moment is the right response. Validation errors stay 422 (invalid_kind, blank_text).

Request

POST
/v1/business_numbers/:id/voice_previews
curl -X POST https://app.phone.inc/api/v1/business_numbers/0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01/voice_previews \
  -H "X-Api-Key: $PHONE_INC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "welcome",
    "text": "Hi, you have reached Harbour & Co."
  }'

Response

{
  "id": "eyJfcmFpbHMiOnsiZGF0YSI6...",
  "kind": "welcome",
  "text": "Hi, you have reached Harbour & Co.",
  "audio_url": "https://app.phone.inc/rails/active_storage/blobs/..."
}