Inbox

Read calls, voicemails, and messages grouped by external phone number, then open a timeline and mark observed activity seen.

The inbox model

An inbox thread is a read view, not a persisted conversation. There is no conversation ID or create-conversation endpoint. Threads aggregate activity across the company's business numbers unless a business-number filter is supplied. Contacts with no activity do not produce threads. An empty timeline read does not create a contact.

Calls linked to a voicemail are represented by the voicemail instead of appearing twice. Threads and timelines are ordered newest first, with deterministic type and record-ID tie-breakers. Calls, voicemails, and messages are included. See Texting and inbox for SMS-specific fields, sending, delivery state, and automatic replies.

Thread properties

  • Name
    phone_number
    Type
    string
    Description
    Normalized E.164 external phone number. This is the thread address.
  • Name
    contact
    Type
    object | null
    Description
    Existing contact reference, including ID, display name, phone, and saved contact fields; null when no contact exists.
  • Name
    last_activity_at
    Type
    string
    Description
    ISO 8601 creation timestamp of the latest activity.
  • Name
    unseen_count
    Type
    integer
    Description
    Number of unseen inbound activity items, including received messages, after call/voicemail folding. Outbound calls do not count as unseen.
  • Name
    business_number_ids
    Type
    array
    Description
    Public IDs of business numbers represented in this thread at the observation boundary.
  • Name
    preview
    Type
    string
    Description
    Call summary, voicemail transcription, or SMS message text, with a fallback label; truncated to 160 characters.
  • Name
    latest_item
    Type
    object
    Description
    Latest activity metadata. Full summary, transcription, message text, and recording URL are omitted.

Activity properties

  • Name
    id
    Type
    string
    Description
    Stable call or voicemail public ID.
  • Name
    type
    Type
    string
    Description
    call, voicemail, or sms. MMS is not implemented.
  • Name
    created_at
    Type
    string
    Description
    ISO 8601 storage timestamp, used for ordering and seen boundaries.
  • Name
    business_number_id
    Type
    string
    Description
    Owning business number public ID.
  • Name
    business_number_name
    Type
    string
    Description
    Owning business number name.
  • Name
    seen_at
    Type
    string | null
    Description
    ISO 8601 timestamp when the team marked this activity seen.
  • Name
    direction
    Type
    string
    Description
    inbound or outbound; voicemails are inbound.
  • Name
    from
    Type
    string
    Description
    Caller phone number.
  • Name
    to
    Type
    string
    Description
    Destination phone number; present on calls.
  • Name
    duration
    Type
    integer | null
    Description
    Call duration or analyzed voicemail recording length in seconds.

Call items also include state, missed, summary, nullable employee with id and name, and has_transcription. Voicemail items include transcription, recording_url, listened, and nullable linked call_id.

Extensible activity types

Treat activity type as extensible. Clients should skip types they do not understand without discarding the thread, and still follow next_cursor when a page contains no renderable items. An unfamiliar latest_item.type must not hide the thread.

The seen endpoint acknowledges the entire thread through observed_at, not just the items a client rendered. Clients that ignore activity types must not assume those items remain unseen after acknowledging that boundary.

Pagination and seen state

List responses include nullable next_cursor. Supply it unchanged as cursor to fetch the next page. Cursors are signed and bound to the company, selected business number, endpoint, and filters. Pages share the first request's observation boundary, so later arrivals do not reshuffle that result set.

Timeline responses also include observed_at. Pass that timestamp to the seen endpoint, rather than generating a timestamp on the client. Seen state is shared by the team, not per employee. The update covers unseen inbound calls and voicemails stored through that boundary, including received messages and folded calls, and preserves later arrivals. Seeing a voicemail does not mark it listened.

Invalid filters, phone numbers, timestamps, or cursors return 422. Future seen timestamps are rejected. Foreign or unknown business numbers return 404; missing authentication returns 401. Company API keys and OAuth tokens are supported. Existing calls, voicemails, and legacy seen/unseen endpoints remain unchanged.


GET/v1/inbox

List the inbox

List grouped activity previews. Filter by optional business_number_id, query, or unseen=true. Text queries use the existing company-isolated keyword and semantic contact search index, including contact name, company name, email, and note, but not call or voicemail bodies. At most 100 indexed contact candidates are resolved to this company's threads; new or edited contacts become searchable after indexing. Phone-only queries accept spaces, parentheses, dots, and dashes and match the normalized phone substring directly, without requiring the search index. Mixed text-and-digit queries are searched intact rather than reduced to digits. The maximum query length is 128 characters. limit defaults to 50 and is clamped to 1–100. Supply cursor for another page.

Request

GET
/v1/inbox
curl 'https://app.phone.inc/api/v1/inbox?limit=50' \
  -H "X-Api-Key: $PHONE_INC_API_KEY"

Response

{
  "threads": [
    {
      "phone_number": "+4523909778",
      "contact": null,
      "last_activity_at": "2026-10-07T09:40:59Z",
      "unseen_count": 1,
      "business_number_ids": [
        "019daef1-085e-762f-98a5-ed28d44138b8"
      ],
      "preview": "Missed call",
      "latest_item": {
        "id": "019daef1-085e-7700-a1b2-c3d4e5f67890",
        "type": "call",
        "direction": "inbound",
        "missed": true
      }
    }
  ],
  "next_cursor": null
}

GET/v1/inbox/:phone_number/activity

List activity

Read one external phone number’s calls, voicemails, and messages. E.164 is recommended; national numbers are normalized using the company country. The path phone number takes precedence over query/body values. Optional business_number_id selects one business number. limit defaults to 50 and is clamped to 1–100. Supply cursor for another page.

Request

GET
/v1/inbox/:phone_number/activity
curl 'https://app.phone.inc/api/v1/inbox/+4523909778/activity?limit=50' \
  -H "X-Api-Key: $PHONE_INC_API_KEY"

Response

{
  "phone_number": "+4523909778",
  "contact": null,
  "items": [
    {
      "id": "019daef1-085e-7700-a1b2-c3d4e5f67890",
      "type": "call",
      "created_at": "2026-10-07T09:40:59Z",
      "business_number_id": "019daef1-085e-762f-98a5-ed28d44138b8",
      "business_number_name": "Office",
      "seen_at": null,
      "direction": "inbound",
      "from": "+4523909778",
      "to": "+4592457318",
      "state": "ended",
      "missed": true,
      "summary": null,
      "duration": 0,
      "employee": null,
      "has_transcription": false
    }
  ],
  "next_cursor": null,
  "observed_at": "2026-10-07T09:41:00Z"
}

POST/v1/inbox/:phone_number/seen

Mark activity seen

Mark this thread seen through the required through timestamp returned as observed_at by the activity endpoint. Optional business_number_id limits the update to that business number. Returns 204 No Content. The operation is idempotent and broadcasts a metadata-only unseen-count invalidation.

Request

POST
/v1/inbox/:phone_number/seen
curl -X POST 'https://app.phone.inc/api/v1/inbox/+4523909778/seen' \
  -H "X-Api-Key: $PHONE_INC_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"through":"2026-10-07T09:41:00Z"}'