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

# Liveness, and the label this build serves by default

> Liveness plus the deployment's own identity. No engine work is done.

`build_id` is the content digest of the sources baked into the deployed
artifact. Two endpoints reporting the same `build_id` are provably the
same build — which is what makes a comparison between two deployments a
test of the transport rather than an accidental comparison of two
different builds.




## OpenAPI

````yaml /api-reference/openapi.yaml get /v1/health
openapi: 3.1.0
info:
  title: Needlepath Context Selection API
  version: 1.0.0
  summary: Select which context records enter a model call, verbatim.
  description: |
    Needlepath decides **which of your records go into a prompt**. You send the
    records you hold — documents, tool results, prior turns — plus the task they
    have to serve and a token budget. Needlepath returns the subset worth
    sending, verbatim, with a rendered block you can paste straight into your
    prompt.

    Three properties shape everything else in this document:

    - **Nothing is stored.** Records ride in on every request. There is no
      session, no upload step, no retention. The service holds no database on
      the request path and its execution role grants log-writing and nothing
      else. See *Retention and trust*.
    - **The same request gets the same answer.** Behaviour is pinned by an
      opaque, immutable `operating_point` label. Retuning mints a *new* label;
      a published label never changes meaning.
    - **It can decline.** When trimming would not pay, the engine stands down
      and hands back a selection that is effectively your input. That is a
      designed outcome, not a failure — see `fallback_used` and `gate`.

    ### Versioning

    URL versions are **major-only**: `/v1`, `/v2`, …. A breaking change mints a
    new URL version; optional additions — a new response field, a new optional
    request field with a safe default, a new operating-point label — ship at the
    existing one. Nothing is served unversioned and there is no implicit
    "latest". A version keeps serving until it is **formally deprecated**, which
    requires a published notice naming the replacement and a sunset date, a
    written migration path, and a notice period that has elapsed before removal.

    ### Forward compatibility, required of clients

    Two rules, both from `INTERFACE.md`, and a client that ignores them will
    break on a change this contract considers non-breaking:

    1. **Ignore response fields you do not recognise.** New optional fields ship
       within `/v1`.
    2. **Do not exhaustively match `gate.reason` or the gate outcome.** The gate
       outcome is an open, extensible enum. Today it takes two values — a
       *select* outcome (`gate.engaged = true`) and a *stand_down* outcome
       (`gate.engaged = false`) — with the specific trigger in `reason`
       (`engage:needle`, `standdown:high_drift`, …). A third outcome,
       *escalate*, is a planned additive change.
  contact:
    name: Needlepath support
    url: https://nextmoca.com
  x-logo:
    altText: Needlepath
servers:
  - url: https://api.nextmoca.com
    description: Needlepath hosted API.
security:
  - bearerAuth: []
tags:
  - name: Selection
    description: The one endpoint that does work.
  - name: Registry
    description: Public, unchanging facts about the deployment.
paths:
  /v1/health:
    get:
      tags:
        - Registry
      summary: Liveness, and the label this build serves by default
      description: |
        Liveness plus the deployment's own identity. No engine work is done.

        `build_id` is the content digest of the sources baked into the deployed
        artifact. Two endpoints reporting the same `build_id` are provably the
        same build — which is what makes a comparison between two deployments a
        test of the transport rather than an accidental comparison of two
        different builds.
      operationId: health
      responses:
        '200':
          description: Healthy.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Health'
              example:
                status: ok
                service: needlepath-hosted-adapter
                endpoint: /v1/context/select
                default_operating_point: np-2026-07-r2
                operating_points:
                  - np-2026-07-r1
                  - np-2026-07-r2
                build_id: 9f1c2b7e4a
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
components:
  schemas:
    Health:
      type: object
      required:
        - status
        - service
        - endpoint
        - default_operating_point
        - operating_points
      properties:
        status:
          type: string
          examples:
            - ok
        service:
          type: string
          examples:
            - needlepath-hosted-adapter
        endpoint:
          type: string
          examples:
            - /v1/context/select
        default_operating_point:
          type: string
        operating_points:
          type: array
          items:
            type: string
        build_id:
          type: string
          description: >-
            Content digest of the sources baked into the deployed artifact.
            Empty when the service runs from a source tree.
    GatewayError:
      type: object
      description: |
        Generated by API Gateway, not by the service. The key is capitalised
        inconsistently between cases (`message` vs `Message`) because these are
        AWS's own bodies passed through unchanged — **match on the status code,
        not on this body.**
      properties:
        message:
          type: string
        Message:
          type: string
  responses:
    Unauthorized:
      description: |
        **No `Authorization` header at all.** Rejected at the gateway before
        anything of ours is invoked, so the body is the platform's, not ours.

        A header that is present but not `Bearer`-shaped is **not** a 401 — it
        reaches authorization and comes back `403`. Wire the two separately:
        **401 = the header never arrived** (fix the client), **403 = it arrived
        and was refused** (fix the credential).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/GatewayError'
          example:
            message: Unauthorized
    Forbidden:
      description: >
        A header arrived and authorization refused it. The reason is
        deliberately

        not returned — a caller learns only that the credential does not work,

        because an error that distinguishes "no such key" from "suspended org"
        is

        an oracle.


        Causes: an `Authorization` header that is present but not
        `Bearer`-shaped;

        an unknown, revoked or malformed key; a suspended org; a control-plane

        projection too stale to vouch for.


        Not retryable. Retrying a 403 will not resolve any of its causes.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/GatewayError'
          example:
            Message: >-
              User is not authorized to access this resource with an explicit
              deny
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        `Authorization: Bearer np_live_…`

        One credential form. There is no query-parameter, cookie or
        `x-api-key` alternative — the legacy `x-api-key` header stopped being
        accepted at the Bearer cutover and now fails authorization.

        Keys are **org-scoped**, never user-scoped, and the secret is shown
        exactly once at mint. Rotation is create-then-revoke.

````