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

# The artifacts a settled job's sealed journal records

> Answers only for a settled job (succeeded, failed, cancelled, interrupted); an interrupted run never sealed its journal, so its job answers 409 `artifact_journal_unavailable`. The manifest is read from the journal the job's receipt names, judged by the one verifier `nika trace verify` runs: the chain must be intact, the seal must verify against a run key that verifier weighs on the server, in the order the server signs (the public half of an explicit `NIKA_RUN_KEY_FILE` · `NIKA_RUN_PUB_FILE` pair, `~/.nika/keys/run-signing.pub`, the retired-key ledger), and the head must be the receipt's `chain_head`. Each entry is one journal event that records a written byte stream with its SHA-256: a file a builtin saved (`nika:chart`, `nika:image_generate`, `nika:tts_generate`, `nika:image_fx`, `nika:image_compose`) at a relative path inside the project and outside its `.nika` (refused by name in any ASCII case, and by device and inode under any other spelling the filesystem folds onto it), its last write winning, or an image an agent's harness sent, kept under `.nika/blobs`. `nika:write` and `nika:edit` journal no hash of what they wrote, so their files are not listed. Every size and digest is the journal's; the download route checks the bytes against them. No filesystem path of the server is exposed.



## OpenAPI

````yaml /api-reference/openapi.json get /v1/jobs/{id}/artifacts
openapi: 3.1.0
info:
  description: >-
    Authenticated loopback remote execution, declarative schedules, verified
    downloads of the artifacts a settled job's sealed journal records, and
    stateless source-only authoring (POST /v1/compile never runs, admits or
    writes). Schedule list/delete/trigger/backfill, /v1/arm, and POST /v1/run
    are absent.
  title: nika serve
  version: 0.124.1
servers:
  - url: http://127.0.0.1
security:
  - bearerAuth: []
paths:
  /v1/jobs/{id}/artifacts:
    get:
      summary: The artifacts a settled job's sealed journal records
      description: >-
        Answers only for a settled job (succeeded, failed, cancelled,
        interrupted); an interrupted run never sealed its journal, so its job
        answers 409 `artifact_journal_unavailable`. The manifest is read from
        the journal the job's receipt names, judged by the one verifier `nika
        trace verify` runs: the chain must be intact, the seal must verify
        against a run key that verifier weighs on the server, in the order the
        server signs (the public half of an explicit `NIKA_RUN_KEY_FILE` ·
        `NIKA_RUN_PUB_FILE` pair, `~/.nika/keys/run-signing.pub`, the
        retired-key ledger), and the head must be the receipt's `chain_head`.
        Each entry is one journal event that records a written byte stream with
        its SHA-256: a file a builtin saved (`nika:chart`,
        `nika:image_generate`, `nika:tts_generate`, `nika:image_fx`,
        `nika:image_compose`) at a relative path inside the project and outside
        its `.nika` (refused by name in any ASCII case, and by device and inode
        under any other spelling the filesystem folds onto it), its last write
        winning, or an image an agent's harness sent, kept under `.nika/blobs`.
        `nika:write` and `nika:edit` journal no hash of what they wrote, so
        their files are not listed. Every size and digest is the journal's; the
        download route checks the bytes against them. No filesystem path of the
        server is exposed.
      parameters:
        - in: path
          name: id
          required: true
          schema:
            format: uuid
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArtifactManifest'
          description: The manifest, bound to the job's receipt
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Error envelope
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: '`job_not_found`: unknown or foreign job id'
        '408':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Request deadline
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: >-
            `job_not_settled`: queued, running or paused ·
            `artifact_journal_unavailable`: no receipt chain head, or no journal
            by the job's identity · `artifact_journal_unverified`: the journal
            is not sealed and intact with the receipt's head
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: '`internal_error`: the server could not read the journal'
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: >-
            `store_busy`: durable job state unavailable · `artifact_capacity`:
            every artifact slot is busy
components:
  schemas:
    ArtifactManifest:
      additionalProperties: false
      description: >-
        A settled job's artifacts, as its sealed journal records them, bound to
        its receipt: `receipt` is the job's own (trace id and chain head
        included), `verdict` the tier its journal attained. At most 1024 entries
        are listed, in journal order; `truncated` says more exist (a download
        still finds every recorded name).
      properties:
        artifacts:
          items:
            $ref: '#/components/schemas/Artifact'
          maxItems: 1024
          type: array
        max_artifact_bytes:
          description: The largest artifact this server downloads (256 MiB by default)
          examples:
            - 268435456
          minimum: 1
          type: integer
        receipt:
          $ref: '#/components/schemas/JobReceipt'
        truncated:
          type: boolean
        verdict:
          enum:
            - sealed
            - anchored
          type: string
      required:
        - receipt
        - verdict
        - max_artifact_bytes
        - truncated
        - artifacts
      type: object
    Error:
      additionalProperties: false
      properties:
        error:
          additionalProperties: false
          properties:
            code:
              type: string
            message:
              type: string
          required:
            - code
            - message
          type: object
      required:
        - error
      type: object
    Artifact:
      additionalProperties: false
      properties:
        event_id:
          description: The id of that journal event
          format: uuid
          type: string
        kind:
          enum:
            - file
            - agent_image
          type: string
        mime:
          description: >-
            The recorded media type, else one derived from the extension, else
            application/octet-stream
          minLength: 3
          type: string
        name:
          description: >-
            Unique within the job: `file/<path>` or `agent_image/<n>.<ext>` (the
            n-th image the job's agents sent that the blob store kept). The
            download route's `{name}`.
          minLength: 1
          type: string
        path:
          description: >-
            A file's project-relative path, as the workflow wrote it
            (normalized). Absent for an agent image.
          minLength: 1
          type: string
        sha256:
          description: SHA-256 of the recorded bytes, as journaled
          pattern: ^[0-9a-f]{64}$
          type: string
        size:
          description: Bytes, as journaled
          minimum: 0
          type: integer
        task:
          description: The task whose event records it
          type: string
      required:
        - name
        - kind
        - size
        - sha256
        - mime
        - event_id
      type: object
    JobReceipt:
      additionalProperties: false
      description: Terminal binding to the exact immutable admitted execution
      properties:
        chain_head:
          minLength: 1
          type: string
        execution_id:
          minLength: 1
          type: string
        job_id:
          format: uuid
          type: string
        origin:
          $ref: '#/components/schemas/JobOrigin'
        snapshot_digest:
          pattern: ^[0-9a-f]{64}$
          type: string
        trace_id:
          minLength: 1
          type: string
      required:
        - job_id
        - execution_id
        - trace_id
        - snapshot_digest
      type: object
    JobOrigin:
      oneOf:
        - additionalProperties: false
          properties:
            kind:
              const: manual
              type: string
          required:
            - kind
          type: object
        - additionalProperties: false
          dependentRequired:
            missed_count:
              - missed_first
            missed_first:
              - missed_count
          properties:
            arm_generation:
              pattern: ^[0-9a-f]{64}$
              type: string
            decision:
              enum:
                - scheduled
                - catch_up
              type: string
            fired_at:
              format: date-time
              type: string
            kind:
              const: schedule
              type: string
            missed_count:
              description: How many slots that silence holds
              minimum: 1
              type: integer
            missed_first:
              description: >-
                First slot of the silence a catch-up-once run answers for, on a
                catch_up firing only; scheduled_for is its last slot
              format: date-time
              type: string
            schedule_id:
              description: >-
                Origin-local identifier, bounded to 255 UTF-8 bytes by the
                server
              maxLength: 255
              minLength: 1
              type: string
            schedule_origin:
              enum:
                - project
                - api
              type: string
            schedule_revision:
              pattern: ^sha256:[0-9a-f]{64}$
              type: string
            scheduled_for:
              format: date-time
              type: string
            slot_id:
              pattern: ^[0-9a-f]{64}$
              type: string
          required:
            - kind
            - schedule_origin
            - schedule_id
            - schedule_revision
            - slot_id
            - decision
            - scheduled_for
            - fired_at
            - arm_generation
          type: object
  securitySchemes:
    bearerAuth:
      description: 'Exactly one Authorization: Bearer value from the token file'
      scheme: bearer
      type: http

````

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