> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lusor.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Page stored SMS messages for a workspace number

> Read-only human inbox. Returns raw stored text and codes, never parsed
OTPs or inferred sender identities. Requires an API key bound to this
exact workspace.
Unknown, foreign, or malformed workspace/number IDs return opaque 404s.
No provider polling, writes, or outbound SMS occurs.

Ordered by received_at DESC, id DESC, including equal timestamps.
Pass nextCursor back unchanged to load older retained history; null
means no further rows were observed. This is not a snapshot: newly
received messages require refreshing the first page and retention may
remove older messages. Reset pagination when workspace, number, or
sender changes. No total, unread count, or complete sender list is implied.
Unknown/repeated query parameters and malformed values return 400.
All responses use Cache-Control: no-store.




## OpenAPI

````yaml /api-reference/openapi.yaml get /v1/workspaces/{workspaceId}/numbers/{phoneNumberId}/messages
openapi: 3.1.0
info:
  title: Lusor API
  version: 0.1.0
  description: |
    Run AI agents on real phones, or drive a phone directly with
    deterministic actions.

    ## Authentication

    Every `/v1/*` endpoint except `GET /v1/health` requires an API key.
    Create one in the Lusor dashboard under **Settings → API Keys**. A key
    is shown once and is bound to one workspace. Revoking it there stops it
    working immediately.

    Send it in either header:

    - `X-Api-Key: <your API key>`
    - `Authorization: Bearer <your API key>`

    Because a key is bound to its workspace, `workspaceId` query and body
    parameters are optional for API-key callers. A request that names a
    different workspace returns an opaque `404`.

    ## Runs

    Use `POST /v1/agents/{id}/turns` to start or continue an agent run.
    Read the run under `/v1/sessions/{id}`; poll
    `GET /v1/sessions/{id}/status` or `GET /v1/sessions/{id}/events` for
    progress.

    ## Errors

    Errors are JSON: `{ "error": "<code>", "message": "<text>" }`. A
    request that fails validation returns `400` in one of two shapes,
    depending on the endpoint: `{ "error": "validation_error", "details":
    { ... } }` (direct phone control actions, for example), or
    `{ "error": "bad_request", "message": "<text>" }` (agent endpoints, for
    example). Branch on `error`.
  contact:
    name: Lusor
    url: https://lusor.ai
  license:
    name: Proprietary
    url: https://lusor.ai/terms
servers:
  - url: https://api.lusor.ai
    description: Production
security:
  - ApiKey: []
  - BearerAuth: []
tags:
  - name: Agents
    description: Persistent agents, the phone each one uses, and their turns (runs).
  - name: Secrets
    description: |
      Secrets saved in a workspace (passwords, sign-in details). A run uses
      them by name through `secrets`; values never travel in a request.
  - name: Sessions
    description: |
      Run records: list, inspect, stop, and read events and artifacts. Start
      a run with `POST /v1/agents/{id}/turns`, or without an agent through
      `POST /v1/workspaces/{workspaceId}/devices/{deviceId}/sessions`.
  - name: LiveView
    description: |
      View-only WebRTC live view of a session's phone: signaling, ICE
      servers, and stream control. API keys get live view only on the
      customer's own phone, not on a Lusor Phone.
  - name: Devices
    description: |
      The phones in your workspace, and reads of their current screen and
      UI tree.
  - name: DeviceVerbs
    description: |
      Direct phone control: deterministic actions (tap, swipe, type, key,
      clear, back, home, recent, screenshot, apps/start, apps/stop) and
      chains of them. On a Lusor Phone, API-key calls meter phone minutes.
  - name: Shell
    description: |
      Restricted shell escape hatch. Commands are checked against a
      denylist and audit-logged. No command output is returned.
  - name: Datasets
    description: Lists a run produced, saved as reusable Datasets.
  - name: Skills
    description: Reusable automation skills (Markdown documents).
  - name: PhoneNumbers
    description: |
      Workspace phone numbers and their stored SMS messages. Read-only for
      API keys.
  - name: Emails
    description: |
      Workspace Agent Mail addresses and stored inbound mail.
      Read-only: there is no compose, reply, or send endpoint, and message
      bodies are returned as raw plain text without HTML execution, remote
      asset fetches, or code extraction.
  - name: Workspaces
    description: The workspace an API key is bound to.
  - name: Catalog
    description: The catalog of apps that can be installed on a Lusor Phone.
  - name: Health
    description: Service health check.
paths:
  /v1/workspaces/{workspaceId}/numbers/{phoneNumberId}/messages:
    get:
      tags:
        - PhoneNumbers
      summary: Page stored SMS messages for a workspace number
      description: >
        Read-only human inbox. Returns raw stored text and codes, never parsed

        OTPs or inferred sender identities. Requires an API key bound to this

        exact workspace.

        Unknown, foreign, or malformed workspace/number IDs return opaque 404s.

        No provider polling, writes, or outbound SMS occurs.


        Ordered by received_at DESC, id DESC, including equal timestamps.

        Pass nextCursor back unchanged to load older retained history; null

        means no further rows were observed. This is not a snapshot: newly

        received messages require refreshing the first page and retention may

        remove older messages. Reset pagination when workspace, number, or

        sender changes. No total, unread count, or complete sender list is
        implied.

        Unknown/repeated query parameters and malformed values return 400.

        All responses use Cache-Control: no-store.
      operationId: listPhoneNumberMessages
      parameters:
        - $ref: '#/components/parameters/WorkspaceIdPath'
        - $ref: '#/components/parameters/PhoneNumberIdPath'
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
          description: Decimal integer without signs, whitespace, or leading zeroes.
        - name: cursor
          in: query
          schema:
            type: string
            minLength: 1
            maxLength: 512
            pattern: ^[A-Za-z0-9_-]+$
          description: Opaque validated pagination cursor from the previous page.
        - name: sender
          in: query
          schema:
            type: string
            minLength: 1
            maxLength: 4096
          description: >-
            Exact case-sensitive stored sender string; no trimming or brand
            inference. Omit to include null senders.
      responses:
        '200':
          description: Bounded page of stored messages (may be empty)
          headers:
            Cache-Control:
              schema:
                type: string
                const: no-store
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PhoneNumberMessageListResponse'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  parameters:
    WorkspaceIdPath:
      name: workspaceId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Workspace UUID. Caller must have access.
    PhoneNumberIdPath:
      name: phoneNumberId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: >-
        Phone-number inventory UUID. Foreign and missing ids return an opaque
        404.
  schemas:
    PhoneNumberMessageListResponse:
      type: object
      additionalProperties: false
      required:
        - data
        - nextCursor
      properties:
        data:
          type: array
          maxItems: 100
          items:
            $ref: '#/components/schemas/PhoneNumberMessage'
        nextCursor:
          type:
            - string
            - 'null'
          description: >-
            Pass unchanged as cursor; null when no older retained rows were
            observed.
    PhoneNumberMessage:
      type: object
      additionalProperties: false
      required:
        - id
        - sender
        - body
        - receivedAt
      properties:
        id:
          type: string
          format: uuid
        sender:
          type:
            - string
            - 'null'
          description: Stored sender, or null when unknown. Not a verified brand identity.
        body:
          type: string
          description: >-
            Raw stored SMS text, including codes. Render as plain text, never
            HTML.
        receivedAt:
          type: string
          format: date-time
          description: Stored receipt timestamp with original database precision.
    ValidationErrorResponse:
      type: object
      required:
        - error
        - details
      properties:
        error:
          type: string
          example: validation_error
        details:
          type: object
          additionalProperties: true
    ErrorResponse:
      type: object
      required:
        - error
        - message
      properties:
        error:
          type: string
        message:
          type: string
  responses:
    ValidationError:
      description: |
        Request validation failed. Either `validation_error` with per-field
        `details`, or `bad_request` with a `message`, depending on the
        endpoint.
      content:
        application/json:
          schema:
            anyOf:
              - $ref: '#/components/schemas/ValidationErrorResponse'
              - $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Authentication required or invalid credentials.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Resource not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: X-Api-Key
      description: Workspace API key, created in the dashboard under Settings → API Keys.
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        The same workspace API key, sent as `Authorization: Bearer <your API
        key>`.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.