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

# What is recorded on frames

> Everything the datasets your key can read say about the frames you name, grouped by frame and named by dataset.

A **baseline** dataset, one keyed by frame, contributes its row for each frame as `values`: the administrative identity, population, buildings, physical and cultural attributes Milsat records, and any baseline your organisation has added or licensed. A **feature** dataset, one of points, lines or polygons, contributes the features bound to each frame as `features`, at most 200 per dataset per request. Feature datasets appear only for a key holding `feature.read`; a narrower key sees baselines alone.

A dataset that records nothing on a frame is simply absent from that frame's list, and a frame id the index does not know comes back with no box and no datasets. Neither is an error.

A dataset licensed per query is charged once per request in which it contributed something, and its id is listed in `charged`. One the organisation's credits cannot cover is left out and named in `leftOut` with the reason, so the rest of the answer still arrives.

At most 100 frame ids per request. Needs `frame.read`.



## OpenAPI

````yaml /api-reference/openapi.json get /v1/frames/data
openapi: 3.1.0
info:
  title: LOCI API
  version: 1.0.0
  summary: >-
    The Milsat spatial index over HTTP: find the frame at a location, the frames
    around it, what is recorded on them, and a worded answer about them.
  description: >-
    Four calls, all under `/v1/frames`, all read-only, all with an API key.


    Nigeria is covered by a grid of **frames**: cells roughly a kilometre
    across, each with a stable numeric id. Every dataset on LOCI falls within
    frames, so a frame id is the key to everything known about a place. The API
    lets your code resolve a location to its frame, list the frames around a
    point, read what the datasets your organisation owns or licenses record on
    those frames, and ask a question about them in plain language.


    Every response is wrapped in an envelope: a success carries `data`, a
    failure carries `error` with a machine-readable `code` and a human
    `message`. Branch on the code; the message may be reworded.


    Send the key as `Authorization: Bearer loci_sk_…`. A key acts for one
    organisation, is read-only, and expires.
servers:
  - url: https://api.staging.loci.ng
    description: The LOCI API, which the app at loci.ng also uses.
  - url: http://localhost:8088
    description: A local development stack, which the examples here were captured against.
security:
  - apiKey: []
tags:
  - name: Frames
    description: The spatial index and what is recorded on it.
paths:
  /v1/frames/data:
    get:
      tags:
        - Frames
      summary: What is recorded on frames
      description: >-
        Everything the datasets your key can read say about the frames you name,
        grouped by frame and named by dataset.


        A **baseline** dataset, one keyed by frame, contributes its row for each
        frame as `values`: the administrative identity, population, buildings,
        physical and cultural attributes Milsat records, and any baseline your
        organisation has added or licensed. A **feature** dataset, one of
        points, lines or polygons, contributes the features bound to each frame
        as `features`, at most 200 per dataset per request. Feature datasets
        appear only for a key holding `feature.read`; a narrower key sees
        baselines alone.


        A dataset that records nothing on a frame is simply absent from that
        frame's list, and a frame id the index does not know comes back with no
        box and no datasets. Neither is an error.


        A dataset licensed per query is charged once per request in which it
        contributed something, and its id is listed in `charged`. One the
        organisation's credits cannot cover is left out and named in `leftOut`
        with the reason, so the rest of the answer still arrives.


        At most 100 frame ids per request. Needs `frame.read`.
      operationId: frameData
      parameters:
        - name: ids
          in: query
          required: true
          description: Comma-separated frame ids, at most 100.
          schema:
            type: string
          example: '2163551'
      responses:
        '200':
          description: One entry per requested frame, in the order asked.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/FrameDataResponse'
                required:
                  - data
              example:
                data:
                  frames:
                    - id: '2163551'
                      bbox:
                        - 7.48751263500003
                        - 9.051434265000069
                        - 7.500301437000076
                        - 9.06200771500005
                      datasets:
                        - layerId: lyr_8142687a47796c6e
                          name: Administrative baseline
                          category: Administrative
                          kind: frames
                          orgId: org-milsat
                          values:
                            adm_lga: ABUJA MUNICIPAL AREA COUNCIL
                            adm_lga_code: '436'
                            adm_state: FCT
                            adm_state_code: '14'
                            adm_ward: GARKI
                            adm_ward_code: '9470'
                            adm_zone: NORTH CENTRAL
                            adm_zone_code: '3'
                        - layerId: lyr_07311eb9fddfe966
                          name: Built environment baseline
                          category: Built environment
                          kind: frames
                          orgId: org-milsat
                          values:
                            bld_ct: '608'
                            bld_dens: '1237.337222089773'
                        - layerId: lyr_96ed00bcae6ecbe5
                          name: Cultural baseline
                          category: Cultural
                          kind: frames
                          orgId: org-milsat
                          values:
                            cul_ctethnfrm: '1'
                            cul_ctethnsta: '5'
                            cul_ctlangfrm: '1'
                            cul_ctlangsta: '8'
                            cul_ethnfrm: Gwandara
                            cul_ethnsta: Gbari, Gwandara, Igbira, Koro, Nupe
                            cul_langfrm: Gwandara
                            cul_langsta: >-
                              Ashe, Begbere-Ejar, Dibo, Gade, Gbagyi, Gbari,
                              Gwandara, Ija-Zuba
                            cul_rururb: Urban
                        - layerId: lyr_ee58d5508da410ea
                          name: Physical baseline
                          category: Physical
                          kind: frames
                          orgId: org-milsat
                          values:
                            phy_elevmean: '522.0260260260264'
                            phy_landcov: '6'
                            phy_sbsiltxtcls: '6'
                            phy_slopemean: '6.229817091881695'
                            phy_tpsiltxtcls: '9'
                        - layerId: lyr_1b81b870d62fe092
                          name: Population baseline
                          category: Population
                          kind: frames
                          orgId: org-milsat
                          values:
                            pop_demest25: '5699'
                            pop_demest26: '5805'
                        - layerId: lyr_1c0ea62e30f89f79
                          name: Urbanisation baseline
                          category: Urbanisation
                          kind: frames
                          orgId: org-milsat
                          values:
                            urb_class: Peri-urban
                            urb_index: '1'
        '400':
          description: '`ids` is missing, or names more than 100 frames. Code `invalid`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: invalid
                  message: ids=frame,frame,… is required
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/InsufficientScope'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/Internal'
components:
  schemas:
    FrameDataResponse:
      type: object
      properties:
        frames:
          type: array
          items:
            $ref: '#/components/schemas/FrameData'
        charged:
          type: array
          items:
            type: string
          description: Ids of per-query datasets this request was charged for.
        leftOut:
          type: array
          items:
            type: object
            properties:
              layerId:
                type: string
              name:
                type: string
              reason:
                type: string
            required:
              - layerId
              - name
              - reason
          description: >-
            Per-query datasets left out because the organisation's credits could
            not cover them, with the reason.
      required:
        - frames
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: Stable and machine-readable. Branch on it.
            message:
              type: string
              description: For people. May be reworded.
          required:
            - code
            - message
      required:
        - error
    FrameData:
      type: object
      properties:
        id:
          type: string
        bbox:
          $ref: '#/components/schemas/BBox'
        datasets:
          type: array
          items:
            $ref: '#/components/schemas/FrameDataset'
      required:
        - id
        - datasets
    BBox:
      type: array
      description: '`[minLon, minLat, maxLon, maxLat]` in degrees.'
      items:
        type: number
      minItems: 4
      maxItems: 4
    FrameDataset:
      type: object
      description: >-
        One dataset's contribution to one frame: `values` for a baseline keyed
        by frame, `features` for a dataset of shapes.
      properties:
        layerId:
          type: string
        name:
          type: string
        category:
          type: string
        kind:
          type: string
          enum:
            - frames
            - project
            - baseline
          description: >-
            `frames` is a baseline keyed by frame; `project` is a dataset of
            points, lines or polygons.
        orgId:
          type: string
          description: The organisation that owns the dataset.
        values:
          type: object
          additionalProperties: true
          description: The baseline's row on this frame. Values are strings as stored.
        features:
          type: array
          items:
            $ref: '#/components/schemas/Feature'
          description: >-
            The features bound to this frame, at most 200 per dataset per
            request.
      required:
        - layerId
        - name
        - kind
        - orgId
    Feature:
      type: object
      description: >-
        A GeoJSON feature from one of your datasets. `properties` carries the
        feature's attributes, plus `_frame`, the frame it is bound to.
      properties:
        type:
          type: string
          const: Feature
        id:
          type: string
        geometry:
          $ref: '#/components/schemas/Geometry'
        properties:
          type: object
          additionalProperties: true
      required:
        - type
        - id
        - geometry
        - properties
    Geometry:
      type: object
      description: A GeoJSON geometry.
      properties:
        type:
          type: string
          example: Polygon
        coordinates:
          description: Positions as `[lon, lat]`, nested as GeoJSON requires for the type.
      required:
        - type
        - coordinates
  responses:
    Unauthorized:
      description: >-
        No credential (`unauthorized`), or a key that is unknown, expired or
        revoked (`invalid_key`). A bad key is not treated as anonymous: the
        `loci_sk_` prefix proves a key was meant.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            none:
              value:
                error:
                  code: unauthorized
                  message: sign in, or send an API key
            invalid:
              value:
                error:
                  code: invalid_key
                  message: that API key is not valid, has expired, or was revoked
    InsufficientScope:
      description: >-
        The key does not carry `frame.read`. Every preset grants it, so this
        only arises on a key minted with an explicit capability list.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: insufficient_scope
              message: this API key does not carry the frame.read scope
    RateLimited:
      description: >-
        A budget is spent. `Retry-After` says how many seconds until the next
        request will pass.
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds to wait.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: rate_limited
              message: too many requests — retry in 5s
    Internal:
      description: >-
        Something failed on the server. The message is deliberately vague; retry
        once.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: internal
              message: could not look up the frame
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: loci_sk_…
      description: >-
        An API key minted in the Developers tab of the LOCI app, sent as
        `Authorization: Bearer loci_sk_…`. Acts for one organisation, is
        read-only, and expires.

````

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