> ## 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.

# The frames around a location, or of an administrative unit

> Frames as a GeoJSON `FeatureCollection` carrying each frame's id and shape, chosen one of three ways.

**By box.** Every frame that touches `bbox`. To get the frames around a point, build a box around it. The grid is roughly 0.01° across, so a box of ±0.01° around a location returns the frame it is in and its neighbours; ±0.05° returns a neighbourhood. The box is `minLon,minLat,maxLon,maxLat` in degrees, GeoJSON axis order.

**By administrative unit.** Every frame in a state, an LGA or a ward, named down the hierarchy: `state=`, `state=&lga=`, or `state=&lga=&ward=`, matched regardless of case. Each level needs the ones above it, because LGA and ward names repeat across the country. The names come from `GET /v1/states`, `/v1/lgas` and `/v1/wards`, or from `GET /v1/frames/admin`.

**By id.** `ids` fetches up to 100 named frames in full, bounding boxes included, and answers with an array of frames rather than a collection.

At most 5,000 frames come back in one response, or fewer with `limit`. A box past that says so with `"truncated": true` rather than failing, and the remedy is a smaller box. A unit past that is **paged**: the response also carries `next`, and sending it back as `after=` returns the following page, in frame-id order, until a page comes without one. Every state is more than one page, and so are the largest LGAs; a ward is one or two.

Needs `frame.read`.



## OpenAPI

````yaml /api-reference/openapi.json get /v1/frames
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.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:
    get:
      tags:
        - Frames
      summary: The frames around a location, or of an administrative unit
      description: >-
        Frames as a GeoJSON `FeatureCollection` carrying each frame's id and
        shape, chosen one of three ways.


        **By box.** Every frame that touches `bbox`. To get the frames around a
        point, build a box around it. The grid is roughly 0.01° across, so a box
        of ±0.01° around a location returns the frame it is in and its
        neighbours; ±0.05° returns a neighbourhood. The box is
        `minLon,minLat,maxLon,maxLat` in degrees, GeoJSON axis order.


        **By administrative unit.** Every frame in a state, an LGA or a ward,
        named down the hierarchy: `state=`, `state=&lga=`, or
        `state=&lga=&ward=`, matched regardless of case. Each level needs the
        ones above it, because LGA and ward names repeat across the country. The
        names come from `GET /v1/states`, `/v1/lgas` and `/v1/wards`, or from
        `GET /v1/frames/admin`.


        **By id.** `ids` fetches up to 100 named frames in full, bounding boxes
        included, and answers with an array of frames rather than a collection.


        At most 5,000 frames come back in one response, or fewer with `limit`. A
        box past that says so with `"truncated": true` rather than failing, and
        the remedy is a smaller box. A unit past that is **paged**: the response
        also carries `next`, and sending it back as `after=` returns the
        following page, in frame-id order, until a page comes without one. Every
        state is more than one page, and so are the largest LGAs; a ward is one
        or two.


        Needs `frame.read`.
      operationId: framesAround
      parameters:
        - name: bbox
          in: query
          required: false
          description: >-
            `minLon,minLat,maxLon,maxLat` in degrees. One of `bbox`, an
            administrative selector, or `ids` is required.
          schema:
            type: string
          example: 7.485,9.048,7.505,9.068
        - name: state
          in: query
          required: false
          description: A state by name, matched regardless of case.
          schema:
            type: string
          example: Katsina
        - name: lga
          in: query
          required: false
          description: >-
            A local government area by name, matched regardless of case. Needs
            `state`: LGA names repeat across states.
          schema:
            type: string
          example: Kafur
        - name: ward
          in: query
          required: false
          description: A ward by name, matched regardless of case. Needs `state` and `lga`.
          schema:
            type: string
          example: Dutsen Kura/Kanya
        - name: limit
          in: query
          required: false
          description: >-
            At most this many frames per response, up to 5,000, which is also
            the default.
          schema:
            type: integer
            minimum: 1
            maximum: 5000
          example: 3
        - name: after
          in: query
          required: false
          description: >-
            The `next` value of the previous page of an administrative unit, to
            continue the walk. Only with `state`, `lga` and `ward`; a box is not
            paged.
          schema:
            type: string
          example: '1000001'
        - name: ids
          in: query
          required: false
          description: >-
            Instead of `bbox`: comma-separated frame ids, at most 100. Returns
            full frames with bounding boxes.
          schema:
            type: string
          example: 2163551,2163725
      responses:
        '200':
          description: >-
            The frames in the box or the unit as a `FeatureCollection`, or, with
            `ids`, an array of frames. Empty when nothing matches.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    oneOf:
                      - $ref: '#/components/schemas/FrameCollection'
                      - type: array
                        items:
                          $ref: '#/components/schemas/Frame'
                required:
                  - data
              examples:
                box:
                  summary: A box around a point, limited to 3
                  description: >-
                    Captured with `limit=3` so the truncation flag shows;
                    coordinate rings are abridged.
                  value:
                    data:
                      type: FeatureCollection
                      features:
                        - type: Feature
                          id: '2163725'
                          geometry:
                            type: Polygon
                            coordinates:
                              - - - 7.4904
                                  - 9.05143
                                - - 7.4805
                                  - 9.05143
                                - - 7.4805
                                  - 9.06201
                                - - 7.4904
                                  - 9.06201
                                - - 7.4904
                                  - 9.05143
                        - type: Feature
                          id: '2163731'
                          geometry:
                            type: Polygon
                            coordinates:
                              - - - 7.4904
                                  - 9.04434
                                - - 7.48158
                                  - 9.04434
                                - - 7.48158
                                  - 9.05143
                                - - 7.4904
                                  - 9.05143
                                - - 7.4904
                                  - 9.04434
                        - type: Feature
                          id: '2163732'
                          geometry:
                            type: Polygon
                            coordinates:
                              - - - 7.49509
                                  - 9.04434
                                - - 7.4904
                                  - 9.04434
                                - - 7.4904
                                  - 9.05143
                                - - 7.49509
                                  - 9.05143
                                - - 7.49509
                                  - 9.04434
                      truncated: true
                ids:
                  summary: Named frames in full
                  value:
                    data:
                      - id: '2163551'
                        geometry:
                          type: Polygon
                          coordinates:
                            - - - 7.5003
                                - 9.05143
                              - - 7.49131
                                - 9.05143
                              - - 7.49129
                                - 9.05145
                              - - 7.48751
                                - 9.05811
                              - - 7.48753
                                - 9.06201
                              - - 7.5003
                                - 9.06201
                              - - 7.5003
                                - 9.05143
                        bbox:
                          - 7.48751
                          - 9.05143
                          - 7.5003
                          - 9.06201
                unit:
                  summary: 'A ward''s frames, limited to 2: the first page'
                  description: >-
                    `state=Katsina&lga=Kafur&ward=Dutsen%20Kura%2FKanya&limit=2`.
                    The ward holds 147 frames, so the response says it was cut
                    short and where to continue; `after=1000001` returns the
                    next two. Coordinate rings are abridged.
                  value:
                    data:
                      type: FeatureCollection
                      features:
                        - type: Feature
                          id: '1000000'
                          geometry:
                            type: Polygon
                            coordinates:
                              - - - 7.57951
                                  - 11.57039
                                - - 7.56961
                                  - 11.57039
                                - - 7.56961
                                  - 11.57326
                                - - …
                        - type: Feature
                          id: '1000001'
                          geometry:
                            type: Polygon
                            coordinates:
                              - - - 7.58942
                                  - 11.57039
                                - - 7.57951
                                  - 11.57039
                                - - 7.57951
                                  - 11.57749
                                - - …
                      truncated: true
                      next: '1000001'
        '400':
          description: >-
            `invalid_bbox` when none of `bbox`, `ids` or a unit is given, or the
            box is malformed; `invalid` when `lga` or `ward` lacks the levels
            above it, `after` is sent with a box, or `ids` is over the cap.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: invalid_bbox
                  message: bbox=minLon,minLat,maxLon,maxLat is required
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/InsufficientScope'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/Internal'
components:
  schemas:
    FrameCollection:
      type: object
      properties:
        type:
          type: string
          const: FeatureCollection
        features:
          type: array
          items:
            $ref: '#/components/schemas/FrameFeature'
        truncated:
          type: boolean
          description: >-
            Present and `true` when the box or unit held more frames than this
            response carries.
        next:
          type: string
          description: >-
            On a unit's page that was cut short: send it back as `after` for the
            following page. Absent on the last page, and always absent for a
            box.
      required:
        - type
        - features
    Frame:
      type: object
      description: A cell of the spatial index.
      properties:
        id:
          type: string
          description: The frame's stable id, a numeric string.
          example: '2163551'
        geometry:
          $ref: '#/components/schemas/Geometry'
        bbox:
          $ref: '#/components/schemas/BBox'
        admin:
          $ref: '#/components/schemas/FrameAdmin'
      required:
        - id
        - geometry
        - bbox
    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
    FrameFeature:
      type: object
      properties:
        type:
          type: string
          const: Feature
        id:
          type: string
        geometry:
          $ref: '#/components/schemas/Geometry'
      required:
        - type
        - id
        - geometry
    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
    BBox:
      type: array
      description: '`[minLon, minLat, maxLon, maxLat]` in degrees.'
      items:
        type: number
      minItems: 4
      maxItems: 4
    FrameAdmin:
      type: object
      description: >-
        The administrative units a frame lies in, as the administrative baseline
        records them. Absent on an index whose units have not been assigned.
      properties:
        state:
          type: string
          example: KATSINA
        stateCode:
          type: string
          example: '3'
        lga:
          type: string
          example: KAFUR
        lgaCode:
          type: string
          example: '169'
        ward:
          type: string
          example: DUTSEN KURA/KANYA
        wardCode:
          type: string
          example: '1673'
        zone:
          type: string
          example: NORTH WEST
        zoneCode:
          type: string
          example: '1'
      required:
        - state
        - lga
  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.