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
    status
    Type
    string
    Description

    provisioning, active, failed, or terminated. Scheduled numbers remain active until termination_at.

  • Name
    termination_at
    Type
    string | null
    Description

    ISO 8601 date when service ends permanently. Null when no termination is scheduled.

  • Name
    released_at
    Type
    string | null
    Description

    ISO 8601 date when the provider release completed. Released numbers are omitted from the list but remain retrievable by ID with their history.

  • Name
    messaging
    Type
    object
    Description

    Provider capabilities: sms and mms each contain boolean can_send and can_receive flags. Clients can use these directly for messaging availability. Currently only inMobile SMS is supported; MMS capabilities are false.

  • 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

    Legacy compatibility field. true when either transcription or recording retention is enabled. Setting this field updates both transcribe_calls and keep_call_recording.

  • Name
    transcribe_calls
    Type
    boolean
    Description

    Whether calls are recorded and transcribed. When keep_call_recording is false, the temporary recording is deleted after transcription completes.

  • Name
    keep_call_recording
    Type
    boolean
    Description

    Whether the call recording is stored, including when transcribe_calls is false.

  • Name
    call_data_retention
    Type
    string
    Description

    When transcriptions, summaries, stored caller context, and call recordings are automatically deleted. One of one_week, one_month, six_months, one_year, or never. New business numbers default to one_year; numbers that existed when retention policies were introduced default to never.

  • 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), either employee_ids (non-empty array of strings) or department_id (public UUID)
TransferConfigEither employee_ids (non-empty array of strings) or department_id (public UUID)
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.

Every generated message (welcome, greeting, message, and each menu option's prompt) is limited to 150 whitespace-separated words and 1,500 characters, excluding leading and trailing whitespace. This is roughly one minute of speech, not an exact audio-duration limit: voice and speaking pace vary. Both limits apply to all three routing configurations and voice previews. Overlong text is rejected with 422 before audio generation; it is never silently truncated.

Transfer configs must select either non-empty employee_ids or a department_id, never both. department_id is a public UUID from the Departments API and works in incoming, outside-hours and no-answer slots. Send employee_ids: [] when replacing employees with a department; send department_id: null when switching back. Without a department, empty employee selection returns 422 and preserves the saved flow. Transfer responses include nullable department_id alongside employee_ids.

Each department has one FIFO queue shared across business numbers and flows. Callers inherit waiting and no-answer rules from the number called, and repeated entry into the same department does not reset their queue timestamp or deadline.

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.
prompt_recordedbooleanRead only. true when the prompt is a recording made in the dashboard, in which case prompt is an empty string.
employee_idsarray of stringsEmployee transfer targets. For either transfer action, select non-empty employee_ids or department_id, never both.
department_idstring or nullDepartment public UUID for TransferConfig or WelcomeTransferConfig. Callers join its shared queue. Send employee_ids: [] when selecting a department, or department_id: null when switching back to employees.

action_type is one of:

action_typeWhat happens when the caller presses the digit
TransferConfigTransfer straight to the selected employees or department.
WelcomeTransferConfigPlay prompt, then transfer to the selected employees or department.
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), employee_ids (resolved to public ids), and nullable department_id. Department menu targets work in incoming, outside-hours, and no-answer menus, using the number's waiting and no-answer settings.

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. A greeting can also be a recording made in the dashboard: the matching welcome_recorded, message_recorded, greeting_recorded, or prompt_recorded flag is true, the text is an empty string, and the audio URL points at the recording. Recordings are not regenerated when the number's voice changes. Sending new text for that field replaces the recording with generated audio, and the flag turns false. Recordings cannot be created through the API. 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) plus each number's messaging capabilities, so a client can tell which numbers can send a text without retrieving each one. 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

{
  "business_numbers": [
    {
      "id": "0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01",
      "name": "Sales",
      "number": "+14155551234",
      "number_formatted": "+1 415-555-1234",
      "messaging": {
        "sms": { "can_send": true, "can_receive": true },
        "mms": { "can_send": false, "can_receive": false }
      }
    },
    {
      "id": "0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c02",
      "name": "Support",
      "number": "+14155555678",
      "number_formatted": "+1 415-555-5678",
      "messaging": {
        "sms": { "can_send": false, "can_receive": false },
        "mms": { "can_send": false, "can_receive": false }
      }
    }
  ]
}

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,
  "transcribe_calls": false,
  "keep_call_recording": false,
  "call_data_retention": "never",
  "incoming_call_config": {
    "type": "PhoneMenuConfig",
    "welcome": "Press 1 for sales, 2 to leave a message",
    "welcome_recorded": false,
    "welcome_audio_url": "https://app.phone.inc/rails/active_storage/blobs/redirect/...",
    "menu_options": [
      {
        "id": 42,
        "digit": "1",
        "action_type": "TransferConfig",
        "prompt": null,
        "prompt_recorded": false,
        "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_recorded": false,
        "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

    Legacy alias that sets both transcribe_calls and keep_call_recording to the supplied value.

  • Name
    transcribe_calls
    Type
    boolean
    Description

    Whether to create call transcriptions.

  • Name
    keep_call_recording
    Type
    boolean
    Description

    Whether to retain the audio after transcription completes.

  • Name
    call_data_retention
    Type
    string
    Description

    Automatic deletion policy for transcriptions and recordings: one_week, one_month, six_months, one_year, or never. New business numbers default to one_year.

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,
  "transcribe_calls": false,
  "keep_call_recording": false,
  "call_data_retention": "never",
  "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, either employee_ids (at least one id) or department_id; optional welcome_audio_preview_id
TransferConfigEither employee_ids (at least one id) or department_id
RejectConfigmessage; optional message_audio_preview_id
VoicemailConfiggreeting; optional greeting_audio_preview_id
PhoneMenuConfigwelcome, menu_options (at least one option); optional welcome_audio_preview_id

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,
  "transcribe_calls": false,
  "keep_call_recording": false,
  "call_data_retention": "never",
  "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,
  "transcribe_calls": false,
  "keep_call_recording": false,
  "call_data_retention": "never",
  "incoming_call_config": {
    "type": "PhoneMenuConfig",
    "welcome": "Press 1 for sales, 2 to leave a message",
    "welcome_recorded": false,
    "welcome_audio_url": "https://app.phone.inc/rails/active_storage/blobs/redirect/...",
    "menu_options": [
      {
        "id": 42,
        "digit": "1",
        "action_type": "TransferConfig",
        "prompt": null,
        "prompt_recorded": false,
        "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_recorded": false,
        "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. Only business_hours is accepted for the schedule; the retired opening_hours request key and response aliases are no longer supported.

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; optional message_audio_preview_id
WelcomeTransferConfigwelcome, either employee_ids (at least one id) or department_id; optional welcome_audio_preview_id
TransferConfigEither employee_ids (at least one id) or department_id
VoicemailConfiggreeting; optional greeting_audio_preview_id
PhoneMenuConfigwelcome, menu_options (at least one option); optional welcome_audio_preview_id

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,
  "transcribe_calls": false,
  "keep_call_recording": false,
  "call_data_retention": "never",
  "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, either employee_ids (at least one id) or department_id; optional welcome_audio_preview_id
TransferConfigEither employee_ids (at least one id) or department_id
RejectConfigmessage; optional message_audio_preview_id
VoicemailConfiggreeting; optional greeting_audio_preview_id
PhoneMenuConfigwelcome, menu_options (at least one option); optional welcome_audio_preview_id

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,
  "transcribe_calls": false,
  "keep_call_recording": false,
  "call_data_retention": "never",
  "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.

To reuse the exact preview when saving incoming, outside-business-hours, or no-answer routing, send its signed id as welcome_audio_preview_id for a welcome/menu, message_audio_preview_id for a rejection, or greeting_audio_preview_id for voicemail. The preview must be unused and match the number, audio kind, and text. Generate a separate preview for each routing slot. An omitted or nonmatching preview uses normal speech generation. 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, up to 150 whitespace-separated words and 1,500 characters. Blank text is rejected with a 422 and code blank_text. Exceeding either limit returns 422 with code text_too_long, without calling the synthesis service.

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, text_too_long). Shorten overlong text before retrying.

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/..."
}

POST/v1/business_numbers/:id/porting_request

Request number porting

Replace an existing business number with your old number. The existing number stays active as a temporary number while our team arranges the carrier transfer. When porting completes, your old number takes over the same business-number ID, routing, and settings. The temporary number is terminated. Keep your current provider subscription until the transfer completes.

Available on Free without purchasing a second business number. The temporary number must be active, unreleased, provisioned by DIDWW, without an inventory assignment, scheduled termination, or any previous porting request (including completed or cancelled requests).

Returns 201 with the porting request's public id, business_number_id, normalized number_to_port, and initial status of requested. This records a request for our team; it does not immediately submit a transfer to the carrier. Invalid or ineligible requests return 422 with an errors object. Numbers outside your company and released numbers return 404.

Attributes

  • Name
    number_to_port
    Type
    string
    Description

    Required. Your old phone number, including its country code. Must match the temporary number's country dial code, differ from the temporary number, and have no open porting request.

  • Name
    tax_id
    Type
    string
    Description

    Required for Danish numbers. A valid eight-digit CVR number, optionally prefixed with DK.

Request

POST
/v1/business_numbers/:id/porting_request
curl -X POST https://app.phone.inc/api/v1/business_numbers/019daef1-085e-73f0-85f6-a71e2d8dd2cc/porting_request \
  -H "X-Api-Key: $PHONE_INC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"number_to_port":"+4533123487","tax_id":"46213564"}'

Response

{
  "id": "019daef1-085f-7000-8000-a71e2d8dd2cc",
  "business_number_id": "019daef1-085e-73f0-85f6-a71e2d8dd2cc",
  "number_to_port": "+4533123487",
  "status": "requested"
}

POST/v1/business_numbers/:id/termination

Terminate a business number

Permanently close a number at the end of its current billing period. It stays active until termination_at. You can cancel termination before that deadline. The number cannot be recovered after closure; call history is retained. Obtain explicit confirmation before sending this request.

The number charge is removed from future bills immediately, without prorating or refunding the current period. The free-number credit moves to the oldest remaining, non-terminating active number. Employee charges and the company subscription are unchanged, including when terminating the last number.

Requires an active subscription and an active number without an ongoing port. Returns 422 if these conditions or a future billing period end are unavailable, and 503 if Stripe cannot be updated. Repeated requests return the same termination date. The deprecated /main_numbers/:id/termination route is also supported.

Required attributes

  • Name
    confirm
    Type
    boolean
    Description

    Must be true to acknowledge permanent termination.

Request

POST
/v1/business_numbers/:id/termination
curl -X POST https://app.phone.inc/api/v1/business_numbers/019daef1-085e-73f0-85f6-a71e2d8dd2cc/termination \
  -H "X-Api-Key: $PHONE_INC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"confirm":true}'

Returns the full business-number object, including:

Response fields

{
  "id": "019daef1-085e-73f0-85f6-a71e2d8dd2cc",
  "status": "active",
  "termination_at": "2026-11-01T00:00:00Z",
  "released_at": null
}

DELETE/v1/business_numbers/:id/termination

Cancel a termination

Cancel a scheduled termination before termination_at. The number stays active and resumes normal renewal. No extra charge is prorated for the current period, which was already paid. The free-number credit is recalculated across the remaining active numbers, so the oldest eligible number receives the discount.

Returns the full business-number object with termination_at: null. Repeating the request on an active number with no scheduled termination succeeds without changing billing. Previously queued closure jobs will not release the number.

Returns 422 at or after the closure deadline, or when billing cannot be restored automatically. Released numbers return 404. Stripe failures return 503 and leave termination scheduled. Requires an active billing subscription. The deprecated /main_numbers/:id/termination route is also supported.

No request body is required.

Request

DELETE
/v1/business_numbers/:id/termination
curl -X DELETE https://app.phone.inc/api/v1/business_numbers/019daef1-085e-73f0-85f6-a71e2d8dd2cc/termination \
  -H "X-Api-Key: $PHONE_INC_API_KEY"

Returns the full business-number object, including:

Response fields

{
  "id": "019daef1-085e-73f0-85f6-a71e2d8dd2cc",
  "status": "active",
  "termination_at": null,
  "released_at": null
}

POST/v1/business_numbers/{business_number_id}/messages

Send an SMS

Send a message from an active inMobile business number. The optional JSON body field format defaults to sms; only sms is currently supported, and mms or unknown formats return 422 before persistence or provider dispatch. Use /business_numbers/:id/messages; the old /business_numbers/:id/sms_messages sending URL is not exposed. The server derives the sender from the selected number, so clients cannot override it.

The authenticated employee must belong to the company that owns the number. Company API keys are supported only while their creator employee still belongs to that company. Keys without a creator employee cannot send SMS. Missing credentials return 401; missing or mismatched employee membership returns 403. Unknown numbers and numbers belonging to another company return 404.

Required attributes

  • Name
    business_number_id
    Type
    string
    Description

    Business number public ID in the URL. Only active inMobile numbers with at most 14 digits can send.

  • Name
    to
    Type
    string
    Description

    Recipient in E.164 format, such as +4523909778. Include the country code. National-format numbers are not accepted.

  • Name
    text
    Type
    string
    Description

    SMS text, between 1 and 10,000 characters. Whitespace-only text is rejected. Encoding is automatic: GSM-7 when possible, UCS-2 for Unicode. Longer messages can require multiple chargeable SMS parts.

Response

The number's messaging.sms.can_send capability must be true, including an associated inventory record marked SMS-capable. If that record is missing or its SMS capability is disabled, sending returns 422 without creating a message or contacting the provider. Its existing provider handles both voice and messaging. The company's messaging feature flag must be enabled by Phone.inc; it defaults to off. While disabled, message endpoints return 404 and messaging.sms.can_send is false. The message is stored before contacting the provider. 202 Accepted does not mean the recipient received it. The body is a persisted SMS activity item, with a stable Phone.inc ID, employee author, timestamps, and delivery state. A replay returns the current state, which may already be delivered, failed, or unknown.

  • Name
    id
    Type
    string
    Description
    Stable Phone.inc message public ID, shared by history and retries.
  • Name
    business_number_id
    Type
    string
    Description
    Sender business number public ID.
  • Name
    from
    Type
    string
    Description
    Server-selected sender in E.164 format.
  • Name
    to
    Type
    string
    Description
    Recipient in E.164 format.
  • Name
    status
    Type
    string
    Description
    Current delivery state, usually accepted after a new send.
  • Name
    sms_count
    Type
    integer
    Description
    Number of SMS parts reported by the provider.
  • Name
    encoding
    Type
    string
    Description
    Provider-selected gsm7 or ucs2 encoding.

Errors and retries

Invalid input or an unsupported sender returns 422 with { "errors": { ... } }. Provider validation rejection also returns 422, under errors.base. Unconfigured SMS sending returns 503. Provider HTTP, transport, or response errors return 502; these use { "error": "...", "id": "..." } and omit private provider details. Provider errors after persistence include the stable message ID. Changed input with a reused idempotency key returns 409. New sends and explicit retries share a limit of 30 attempts per business number per rolling minute (429, Retry-After: 60); safe replays do not consume another attempt.

Provider blacklist protection remains enabled. Scheduling, bulk recipients, custom sender IDs, and caller-supplied callback URLs are not exposed.

Request

POST
/v1/business_numbers/{business_number_id}/messages
curl -X POST https://app.phone.inc/api/v1/business_numbers/0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01/messages \
  -H "X-Api-Key: $PHONE_INC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":"+4523909778","text":"Your appointment is confirmed.","idempotency_key":"appointment-1"}'

Response

{
  "id": "019daef1-085e-73f0-85f6-a71e2d8dd2cc",
  "type": "message",
  "format": "sms",
  "created_at": "2026-10-06T10:41:00.000000Z",
  "business_number_name": "Sales",
  "seen_at": "2026-10-06T10:41:00.000000Z",
  "direction": "outbound",
  "text": "Your appointment is confirmed.",
  "author": { "type": "employee", "id": "019daef1-085e-73f0-85f6-a71e2d8dd2cd", "name": "Lea" },
  "received_at": null,
  "delivered_at": null,
  "failure_code": null,
  "can_retry": false,
  "business_number_id": "0193f4a9-7c34-7c00-9e3d-2b2b8a7f1c01",
  "from": "+4592450113",
  "to": "+4523909778",
  "status": "accepted",
  "sms_count": 1,
  "encoding": "gsm7"
}