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

# Upload an artifact

> Uploads a file a run produced to CliqHub and returns its id and a download link. Agents
call this through the SDK. The run must be `running` or `awaiting_input`. Send text as
UTF-8 in `content`, or binary as base64 with `encoding: "base64"`.

Size: an artifact may be up to 50 MB (`CLIQ_ARTIFACT_MAX_MB` changes it), text or binary.
This route accepts request bodies big enough for that limit once base64 encoded (about
68 MB by default); every other route stays at 10 MB.

No credential is needed from this machine. From another host, send `Authorization: Bearer` with a dispatch token CliqHub signed for this daemon or a `cliq_tok_…` personal token of a user in the daemon's realm; this only works once the daemon is connected to CliqHub. See [Authentication](/daemon-api/overview#authentication).



## OpenAPI

````yaml /openapi/daemon-by-tag/daemon-artifacts.yaml post /v1/runs/artifacts/submit
openapi: 3.1.0
info:
  title: cliqd API
  version: 1.9.48
  description: >-
    HTTP API of `cliqd`, the local Cliq daemon. Generated from the daemon source
    by `scripts/generate_daemon_openapi.mjs` — do not edit by hand. See the
    [overview](/daemon-api/overview).
servers:
  - url: http://127.0.0.1:4900
    description: Local daemon (default port; `CLIQ_DAEMON_PORT` changes it)
security: []
tags:
  - name: Daemon Artifacts
    description: >-
      Files a run produces (reports, patches, screenshots), stored by CliqHub.
      An agent uploads

      them through its daemon while the run is going; anyone who can see the run
      reads them

      from CliqHub. Both endpoints call CliqHub directly, so the daemon must be
      signed in.
paths:
  /v1/runs/artifacts/submit:
    post:
      tags:
        - Daemon Artifacts
      summary: Upload an artifact
      description: >-
        Uploads a file a run produced to CliqHub and returns its id and a
        download link. Agents

        call this through the SDK. The run must be `running` or
        `awaiting_input`. Send text as

        UTF-8 in `content`, or binary as base64 with `encoding: "base64"`.


        Size: an artifact may be up to 50 MB (`CLIQ_ARTIFACT_MAX_MB` changes
        it), text or binary.

        This route accepts request bodies big enough for that limit once base64
        encoded (about

        68 MB by default); every other route stays at 10 MB.


        No credential is needed from this machine. From another host, send
        `Authorization: Bearer` with a dispatch token CliqHub signed for this
        daemon or a `cliq_tok_…` personal token of a user in the daemon's realm;
        this only works once the daemon is connected to CliqHub. See
        [Authentication](/daemon-api/overview#authentication).
      operationId: daemon_post_runs_artifacts_submit
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                run_id:
                  description: Run id or run name
                  type:
                    - string
                    - number
                phase:
                  description: Phase that produced the artifact
                  type:
                    - string
                    - number
                name:
                  description: Artifact file name
                  type:
                    - string
                    - number
                content:
                  type: string
                  description: Content (UTF-8, or base64 with `encoding`)
                mime_type:
                  description: Content type
                description:
                  description: Human description
                encoding:
                  description: '`base64` when `content` is base64-encoded'
              required:
                - run_id
                - phase
                - name
                - content
              additionalProperties: {}
            examples:
              text:
                summary: A Markdown report
                value:
                  run_id: 0c8d7e6f-5a4b-4c3d-9e2f-1a0b9c8d7e6f
                  phase: review
                  name: review.md
                  content: |
                    ## Findings

                    1. Token in config.ts
                  mime_type: text/markdown
                  description: Findings from the review phase
              binary:
                summary: A PNG screenshot
                value:
                  run_id: fix-login-timeout
                  phase: verify
                  name: login.png
                  content: >-
                    iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==
                  encoding: base64
                  mime_type: image/png
      responses:
        '200':
          description: Success.
          content:
            application/json:
              schema:
                type: object
                required:
                  - ok
                  - data
                properties:
                  ok:
                    type: boolean
                    const: true
                  data:
                    $ref: '#/components/schemas/ArtifactUploaded'
              example:
                ok: true
                data:
                  artifact_id: 8f7e6d5c-4b3a-4291-8e7f-6a5b4c3d2e1f
                  name: review.md
                  download_url: https://files.cliqhub.io/a/8f7e6d5c?sig=…
                  size_bytes: 2048
        '400':
          description: >-
            `BAD_REQUEST` — The request body is larger than the artifact upload
            limit, or is not valid JSON.


            `PAYLOAD_INVALID` — The body (query string for `GET`) fails the
            request schema. `details` lists each issue.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                BAD_REQUEST:
                  summary: BAD_REQUEST
                  value:
                    ok: false
                    error:
                      code: BAD_REQUEST
                      message: 'Request body could not be read: request entity too large'
                PAYLOAD_INVALID:
                  summary: PAYLOAD_INVALID
                  value:
                    ok: false
                    error:
                      code: PAYLOAD_INVALID
                      message: >-
                        run_id: run_id is required; phase: phase is required;
                        name: name is required; content: content must be a
                        string
                      details:
                        - path: run_id
                          message: run_id is required
                        - path: phase
                          message: phase is required
                        - path: name
                          message: name is required
                        - path: content
                          message: content must be a string
        '401':
          description: >-
            `UNAUTHORIZED` — A caller on another host sent no `Authorization:
            Bearer` token, or one that does not verify (expired, wrong
            audience).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                UNAUTHORIZED:
                  summary: UNAUTHORIZED
                  value:
                    ok: false
                    error:
                      code: UNAUTHORIZED
                      message: Missing or invalid Authorization Bearer token
        '403':
          description: >-
            `WEB_REQUEST_REFUSED` — The request carries an `Origin` header (it
            came from a web page).


            `HOST_NOT_LOCAL` — A loopback caller addressed a `Host` other than
            localhost (DNS rebinding guard).


            `LOCAL_ONLY` — The daemon isn't connected to CliqHub (no dispatch
            key) and the caller is on another host.


            `FORBIDDEN` — A `cliq_tok_…` token's user is not in this daemon's
            realm ACL, or the ACL is not loaded yet.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                WEB_REQUEST_REFUSED:
                  summary: WEB_REQUEST_REFUSED
                  value:
                    ok: false
                    error:
                      code: WEB_REQUEST_REFUSED
                      message: cliqd doesn't accept requests from web pages
                HOST_NOT_LOCAL:
                  summary: HOST_NOT_LOCAL
                  value:
                    ok: false
                    error:
                      code: HOST_NOT_LOCAL
                      message: cliqd only answers requests addressed to localhost
                LOCAL_ONLY:
                  summary: LOCAL_ONLY
                  value:
                    ok: false
                    error:
                      code: LOCAL_ONLY
                      message: >-
                        This cliqd isn't connected to CliqHub yet, so from
                        another machine it only accepts a local token (minted by
                        tokens/create on the machine running cliqd)
                FORBIDDEN:
                  summary: FORBIDDEN
                  value:
                    ok: false
                    error:
                      code: FORBIDDEN
                      message: Access denied — identity not in realm ACL
        '404':
          description: '`RUN_NOT_FOUND` — No run has this id or name.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                RUN_NOT_FOUND:
                  summary: RUN_NOT_FOUND
                  value:
                    ok: false
                    error:
                      code: RUN_NOT_FOUND
                      message: Run 'fix-login-timeout' not found
        '409':
          description: >-
            `RUN_INVALID_STATE` — The run has finished; artifacts can only be
            added while it is `running` or `awaiting_input`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                RUN_INVALID_STATE:
                  summary: RUN_INVALID_STATE
                  value:
                    ok: false
                    error:
                      code: RUN_INVALID_STATE
                      message: >-
                        Run is in state 'completed', artifacts can only be
                        submitted to running or awaiting_input runs
        '413':
          description: >-
            `PAYLOAD_TOO_LARGE` — The decoded content is larger than the
            artifact limit (50 MB unless `CLIQ_ARTIFACT_MAX_MB` is set).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                PAYLOAD_TOO_LARGE:
                  summary: PAYLOAD_TOO_LARGE
                  value:
                    ok: false
                    error:
                      code: PAYLOAD_TOO_LARGE
                      message: 'Artifact too large: ~73400320 bytes exceeds 50 MB limit'
        '422':
          description: '`HUB_NOT_CONFIGURED` — This daemon is not signed in to CliqHub.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                HUB_NOT_CONFIGURED:
                  summary: HUB_NOT_CONFIGURED
                  value:
                    ok: false
                    error:
                      code: HUB_NOT_CONFIGURED
                      message: Hub session not configured — run `cliq login` first
        '500':
          description: >-
            `INTERNAL_ERROR` — CliqHub could not be reached, or another
            unexpected fault. The cause is in the cliqd log.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                INTERNAL_ERROR:
                  summary: INTERNAL_ERROR
                  value:
                    ok: false
                    error:
                      code: INTERNAL_ERROR
                      message: >-
                        cliqd hit an unexpected error (request 7f3a…). Details
                        are in the cliqd log.
        '502':
          description: >-
            `HUB_REQUEST_FAILED` — CliqHub refused the upload (for example no
            storage configured, or the run is not known to CliqHub yet).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                HUB_REQUEST_FAILED:
                  summary: HUB_REQUEST_FAILED
                  value:
                    ok: false
                    error:
                      code: HUB_REQUEST_FAILED
                      message: 'Hub artifacts/submit failed: HTTP 503'
      security:
        - {}
        - DaemonBearer: []
components:
  schemas:
    ArtifactUploaded:
      type: object
      required:
        - artifact_id
        - name
        - download_url
        - size_bytes
      properties:
        artifact_id:
          type: string
          description: >-
            CliqHub's id for the artifact. Agents refer to it as
            `cliq://artifacts/<id>`.
          example: 8f7e6d5c-4b3a-4291-8e7f-6a5b4c3d2e1f
        name:
          type: string
          example: review.md
        download_url:
          type: string
          format: uri
          description: >-
            A presigned link to download the file. It expires; get a fresh one
            with Get an artifact.
          example: https://files.cliqhub.io/a/8f7e6d5c?sig=…
        size_bytes:
          type: integer
          description: Stored size in bytes (after base64 decoding).
          example: 2048
    ErrorReply:
      type: object
      description: >-
        Every failure. Switch on `error.code` — it is stable; `message` is for
        people and may change.
      required:
        - ok
        - error
      properties:
        ok:
          type: boolean
          const: false
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Stable error code. See [Errors](/daemon-api/errors).
              example: TEAM_NOT_FOUND
            message:
              type: string
              description: What went wrong and, where possible, what to do.
              example: Team 'acme/code-review' not found
            details:
              description: >-
                Structured detail when there is some: the list of schema issues
                for `PAYLOAD_INVALID`, the agent problems for
                `TEAM_AGENT_CONFIG_REQUIRED`, …
  securitySchemes:
    DaemonBearer:
      type: http
      scheme: bearer
      description: >-
        Not needed from the same machine. From another host: a dispatch JWT
        CliqHub signed for this daemon, or a `cliq_tok_…` personal token whose
        user is in the daemon's realm.

````

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