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

# Upload a file to attach to a comment on a work item

> Stores one file and answers its attachment id. A comment, a follow-up or a review note then names the id in `attachments`. The body is the file's raw bytes and `Content-Type` is its media type. The other values travel in headers: `X-Attachment-Filename` (percent-encoded), `X-Attachment-Sha256` (the lowercase hex digest of the bytes) and `X-Client-Attachment-Id` (a key that makes a retried upload store one attachment). A file is at most 8 MiB. Allowed types: PNG, JPEG, GIF and WebP images, MP4 and WebM video, PDF, plain text, CSV, Markdown, JSON, NDJSON, ZIP and gzip. SVG and HTML are refused. The caller is a credential in the `Authorization` header, or an upload token in the `token` query value with no header. A token is minted for one file by the dashboard. Uploads are counted per caller: 30 per 10 minutes on the free tier and 120 on the paid tier. A client attachment id used again with the same bytes returns the stored attachment; with different bytes it is refused (`attachment_conflict`).



## OpenAPI

````yaml /openapi.yaml post /v1/work-items/{workItemId}/attachments
openapi: 3.0.3
info:
  contact:
    email: hello@outerlayer.ai
    url: https://www.outerlayer.ai
  description: >-
    The OuterLayer Gateway API lets you ingest coding-agent sessions and record
    evidence of work programmatically.


    Most teams reach it through the `outerlayer` CLI, which calls it for them.

    Call it directly to build your own integration or to automate what the
    dashboard does.


    Versioning: every endpoint is prefixed with `/v1/`. Breaking changes ship
    under a new version prefix (`/v2/`, etc.) with a 90-day-minimum deprecation
    window; anything additive lands on the current prefix.


    Vocabulary: the dashboard calls this API's `app` a **factory** — the unit
    that owns a set of repositories, the agent sessions worked on them, and the
    evidence they produce. They are the same entity. The API keeps `app` in its
    paths, headers, and field names because those are a published contract; only
    the product surface was renamed.
  title: OuterLayer Gateway API
  version: '1.0'
servers:
  - description: Production (OuterLayer Cloud)
    url: https://api.outerlayer.ai
  - description: Local dev server (self-hosted gateway)
    url: http://localhost:9418
security:
  - AppId: []
    BearerAuth: []
tags:
  - description: >-
      What a CLI login token can read about its owner without naming a factory,
      such as the factories they can use.
    name: Account
  - description: >-
      The route a fleet machine asks for its next managed build on. A fleet
      machine is a machine OuterLayer operates.
    name: Fleet
  - description: >-
      The CLI version a gateway names to its runners, set with the gateway's
      runner version key.
    name: Runner version
  - description: >-
      Coding-agent session ingest (outerlayer sync) and content-addressed
      session images.
    name: Agents
  - description: >-
      Evidence artifacts (screenshots, recordings, reports, logs) emitted as
      proof of a change and anchored to pull requests.
    name: Artifacts
  - description: >-
      Pass/fail outcomes of checks run in your own CI or compute, anchored to
      pull requests with the run URL as proof.
    name: Emitted Results
  - description: >-
      The acceptance criteria of a work item, recorded as one list. The Criteria
      tab, its count and the item status read that list.
    name: Criteria
  - description: >-
      What any agent found wrong about a change under review or about a rule it
      ran on, recorded on a work item.
    name: Findings
  - description: >-
      Find, file and edit the issue a spec lives in, through OuterLayer, with no
      tracker credential on the caller's side.
    name: Specs
  - description: >-
      Add or remove a source's statement that it is working on an issue or pull
      request, and read what is currently live.
    name: Work Items
  - description: >-
      What the factory's GitHub App installation lets builds do on each
      connected repository, and whether each default branch requires a pull
      request.
    name: Repositories
  - description: >-
      The runs of a schedule automation: a runner claims a run, asks for its
      read token and ends it, and the run's agent reports each issue it found or
      that it found nothing.
    name: Schedule runs
  - description: >-
      A runner host's heartbeat — its CLI version, slots and last request for
      work — and the factory's list of hosts with a derived status.
    name: Hosts
  - description: Query server feature availability.
    name: Capabilities
  - description: Per-model LLM pricing data. Public, unauthenticated.
    name: Pricing
  - description: >-
      Create, list, and revoke factory API keys. Plaintext returned exactly once
      at creation.
    name: API Keys
  - description: >-
      Factory CRUD — a factory is owned by an organization and is the unit every
      other resource hangs off. Lets a headless agent provision one without the
      dashboard.
    name: Apps
  - description: >-
      Agent-coding session list and full transcript reads, with actor-privacy
      controls for machine keys.
    name: Sessions
  - description: >-
      Per-model token spend and fleet-wide agent behavior tiles, including
      two-window comparisons.
    name: Metrics
  - description: Synced-commit history of the app's `.outerlayer/` context tree.
    name: Context
  - description: >-
      Session→PR attribution: which agent sessions produced which pull requests,
      and what each attributed PR cost.
    name: PRs
  - description: Service health checks.
    name: Health
  - description: >-
      Org member and role administration, authenticated with an org-scoped
      management API key (`olk_…`) minted in the dashboard's settings.
    name: Org Management
  - description: OAuth 2.1 discovery metadata for MCP connector clients.
    name: OAuth
paths:
  /v1/work-items/{workItemId}/attachments:
    post:
      tags:
        - Work Items
      summary: Upload a file to attach to a comment on a work item
      description: >-
        Stores one file and answers its attachment id. A comment, a follow-up or
        a review note then names the id in `attachments`. The body is the file's
        raw bytes and `Content-Type` is its media type. The other values travel
        in headers: `X-Attachment-Filename` (percent-encoded),
        `X-Attachment-Sha256` (the lowercase hex digest of the bytes) and
        `X-Client-Attachment-Id` (a key that makes a retried upload store one
        attachment). A file is at most 8 MiB. Allowed types: PNG, JPEG, GIF and
        WebP images, MP4 and WebM video, PDF, plain text, CSV, Markdown, JSON,
        NDJSON, ZIP and gzip. SVG and HTML are refused. The caller is a
        credential in the `Authorization` header, or an upload token in the
        `token` query value with no header. A token is minted for one file by
        the dashboard. Uploads are counted per caller: 30 per 10 minutes on the
        free tier and 120 on the paid tier. A client attachment id used again
        with the same bytes returns the stored attachment; with different bytes
        it is refused (`attachment_conflict`).
      operationId: post-work-item-attachment
      parameters:
        - in: path
          name: workItemId
          required: true
          schema:
            type: string
        - in: query
          name: token
          required: false
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                properties:
                  data:
                    properties:
                      created:
                        type: boolean
                      filename:
                        type: string
                      id:
                        type: string
                      kind:
                        enum:
                          - image
                          - video
                          - pdf
                          - text
                          - file
                        type: string
                      mediaType:
                        type: string
                      sizeBytes:
                        type: number
                    required:
                      - id
                      - filename
                      - mediaType
                      - kind
                      - sizeBytes
                      - created
                    type: object
                required:
                  - data
                type: object
          description: The upload was a retry; the stored attachment is returned.
        '201':
          content:
            application/json:
              schema:
                properties:
                  data:
                    properties:
                      created:
                        type: boolean
                      filename:
                        type: string
                      id:
                        type: string
                      kind:
                        enum:
                          - image
                          - video
                          - pdf
                          - text
                          - file
                        type: string
                      mediaType:
                        type: string
                      sizeBytes:
                        type: number
                    required:
                      - id
                      - filename
                      - mediaType
                      - kind
                      - sizeBytes
                      - created
                    type: object
                required:
                  - data
                type: object
          description: The attachment was stored.
        '400':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: A required header is missing, or the bytes do not match the digest.
        '401':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: Missing or invalid credential.
        '402':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: The organization is read-only (`billing_read_only`).
        '403':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: >-
            The credential lacks the permission, or the upload token does not
            match the file (`attachment_token_invalid`).
        '404':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: No such work item.
        '409':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: >-
            The client attachment id already holds a different file
            (`attachment_conflict`).
        '413':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: The file is over 8 MiB (`attachment_too_large`).
        '415':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: The media type is not allowed (`attachment_type_refused`).
        '429':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: >-
            Rate limit exceeded. Retry after the delay in the Retry-After
            header.
        '503':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: >-
            Object storage did not answer; retry with the same client attachment
            id.
      security:
        - AppId: []
          BearerAuth: []
        - AttachmentToken: []
components:
  securitySchemes:
    AppId:
      description: Factory id the request is scoped to.
      in: header
      name: X-Outerlayer-App-Id
      type: apiKey
    BearerAuth:
      description: API key (sk_outerlayer_*)
      scheme: bearer
      type: http
    AttachmentToken:
      description: >-
        A signed attachment token: an upload token for one file, or the download
        token in a threads read.
      in: query
      name: token
      type: apiKey

````

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