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

> ## Agent Instructions
> These docs target Mesh SDK v0.27.0. Match the installed package and binding before generating code. Start at /getting-started/agents for task-specific reading paths.
> Call the company and product Offline Protocol, never Offline alone. Current packages: @offline-protocol/mesh-sdk 0.27.0 (React Native), @offline-protocol/id-react 0.2.0, @offline-protocol/id-react-native 0.3.3, @offline-protocol/pol 0.1.2 and @offline-protocol/cli 0.2.6. Canonical docs URLs start with https://www.offlineprotocol.com/docs.
> The Mesh SDK runs in a native app or gateway. A browser OfflineID SDK integration does not provide browser mesh transport. Local mesh operation does not require a portal account or API key. The Mesh SDK appId is a mesh app identifier the developer chooses, not the portal App ID (app_...) that OfflineID and Proof of Location require.
> Service RPC is signed plaintext in v0.27.0. Message delivery, durable local acceptance and backend commit are distinct outcomes. Use the workflow guide for the required application logic.
> Offline Protocol CLI 0.2.6 is on npm (@offline-protocol/cli, command offline). Its local MCP server, named offline-protocol, runs with npx -y @offline-protocol/cli@0.2.6 mcp serve and requires no login or key. Hosted MCP is at https://mcp.offlineprotocol.com/mcp with an app API key in Authorization: Bearer and the matching App ID in x-app-id; organization keys are rejected, and Claude Desktop, Claude.ai and ChatGPT cannot use it. Follow /tools/overview for setup and do not invent commands beyond it. MCP provides integration context and planning, not mesh execution; file-writing tools are local only.
> Phone Wi-Fi Direct and MultipeerConnectivity carry no data in v0.27.0. Use BLE or a provisioned relay. The receiver core ACKs before application persistence; use application acceptance for durable workflows.
> Proof of Location is Sepolia testnet witness evidence, not zero-knowledge proof or proof of presence. The geohash is public onchain. Read /proof-of-location/security before integration.

# Get network map

> Public and unauthenticated. Returns device counts per area for the network map, never a device's or profile's location. Responses are paginated: page defaults to 1 and limit to 50. Each client IP can make 60 requests a minute.

This public endpoint needs no API key or user token. It returns device counts per area, in three tiers, and never returns a device's or profile's location:

* Areas of 0.1 degree (about 11 km) with at least three devices.
* Devices left over are rolled up into areas of 1 degree (about 111 km), published with at least three devices.
* Devices still left over go into wider regions of 5 degrees (about 550 km), published with any count and marked `"coarse": true`. A wider region places a device only within a region hundreds of kilometers across.

Every device is counted in exactly one area, so `devices_published` equals `devices_total`. `format=cells` returns every tier as `{lat, lon, count, size_deg}` (plus `coarse` on wider regions). The default point list (one `{lat, lon}` per device at its area's center) leaves wider regions out; `nodes_total` gives its length.

## Pagination

Both formats are paginated. `page` starts at 1 and `limit` defaults to 50, so a request without them returns the first 50 points. Each response reports the `page` and `limit` it applied and how many items it `returned`. Request further pages until `returned` is less than `limit`, or size one request from `nodes_total` or `cells_total`:

```bash theme={null}
curl "https://api.offlineprotocol.com/api/v1/stats/nodes?format=cells&limit=500&page=1"
```

Responses are cached for 60 seconds. Each client IP can make 60 requests a minute; the `ratelimit-remaining` header shows what is left, and a `429` carries `Retry-After`.


## OpenAPI

````yaml get /stats/nodes
openapi: 3.1.0
info:
  title: Offline Protocol hosted API
  version: 1.0.0
  description: >-
    Hosted OfflineID authentication, profiles and connections. Send a user JWT
    and X-App-Id; a portal API key is not a user token. Endpoint-specific
    availability and response envelopes are documented below.
servers:
  - url: https://api.offlineprotocol.com/api/v1
security: []
paths:
  /stats/nodes:
    get:
      summary: Get network map
      description: >-
        Public and unauthenticated. Returns device counts per area for the
        network map, never a device's or profile's location. Responses are
        paginated: page defaults to 1 and limit to 50. Each client IP can make
        60 requests a minute.
      parameters:
        - name: page
          in: query
          required: false
          description: Page number, starting at 1. Defaults to 1.
          schema:
            type: integer
            minimum: 1
            default: 1
        - name: limit
          in: query
          required: false
          description: >-
            Items per page: points in the default format, areas with
            format=cells. Defaults to 50; larger values are capped by the
            service.
          schema:
            type: integer
            minimum: 1
            default: 50
        - name: format
          in: query
          required: false
          description: >-
            Set to cells to return every area with its count instead of one
            point per device.
          schema:
            type: string
            enum:
              - cells
        - name: reverse
          in: query
          required: false
          description: Set to true to page from the end of the list.
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      devices_total:
                        type: integer
                        description: Devices with a location.
                      devices_published:
                        type: integer
                        description: >-
                          Devices counted in a published area. Equals
                          devices_total while the wide-region tier is on.
                      devices_coarse:
                        type: integer
                        description: Devices counted only in 5 degree wide regions.
                      nodes_total:
                        type: integer
                        description: >-
                          Length of the full point list (devices_published minus
                          devices_coarse).
                      cells_total:
                        type: integer
                        description: Published areas across all tiers.
                      grid_deg:
                        type: number
                        description: Finest area size in degrees (0.1).
                      parent_grid_deg:
                        type: number
                        description: Roll-up area size in degrees (1).
                      coarse_grid_deg:
                        type: number
                        description: Wide region size in degrees (5).
                      min_devices_per_cell:
                        type: integer
                        description: >-
                          Minimum devices in a published 0.1 or 1 degree area
                          (3).
                      page:
                        type: integer
                        description: Page returned, starting at 1.
                      limit:
                        type: integer
                        description: Items per page applied to this response.
                      returned:
                        type: integer
                        description: Items in this page.
                      nodes:
                        type: array
                        description: >-
                          Default format. One point per device at its area's
                          center; wide regions are left out.
                        items:
                          type: object
                          properties:
                            lat:
                              type: number
                            lon:
                              type: number
                          required:
                            - lat
                            - lon
                      cells:
                        type: array
                        description: >-
                          Returned with format=cells. Every published area, all
                          tiers.
                        items:
                          type: object
                          properties:
                            lat:
                              type: number
                              description: Area center latitude.
                            lon:
                              type: number
                              description: Area center longitude.
                            count:
                              type: integer
                              description: Devices in the area.
                            size_deg:
                              type: number
                              description: 'Area size in degrees: 0.1, 1 or 5.'
                            coarse:
                              type: boolean
                              description: Present and true on 5 degree wide regions.
                          required:
                            - lat
                            - lon
                            - count
                            - size_deg
                    required:
                      - devices_total
                      - devices_published
                      - devices_coarse
                      - nodes_total
                      - cells_total
                      - grid_deg
                      - parent_grid_deg
                      - coarse_grid_deg
                      - min_devices_per_cell
                      - page
                      - limit
                      - returned
                required:
                  - message
                  - data
        '429':
          description: Rate limited; wait for the Retry-After header
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Service error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Error:
      type: object
      properties:
        message:
          type: string
        data:
          type:
            - object
            - 'null'
        error:
          type: object
          properties:
            message:
              type: string
            code:
              type: string
            retryAfter:
              type: integer
            currentHourCount:
              type: integer
            limit:
              type: integer
      required:
        - message

````