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

# API introduction

> The JSON API under /api/v1 — base URLs, conventions, and which parts are meant for which caller.

`apps/web` serves a JSON API under `/api/v1`. The CLI is its main client; the dashboard is
the other.

<Note>
  This reference is generated from an OpenAPI 3.1 document derived by reading the route
  handlers in `apps/web/app/api/v1` and the shared types in `packages/contracts`. Nothing
  here is inferred from naming.

  It documents the surface a developer and the Myrqen CLI use. Platform-administration and
  billing endpoints exist in the application but are operator-only and are deliberately not
  published here — a self-hosted operator should read the route handlers directly.
</Note>

## Base URLs

<Warning>
  **There is no hosted Myrqen service today.** `https://api.myrqen.cc` is the endpoint the CLI
  ships as its default, and it is not deployed — requests to it do not resolve. Every example
  in this reference therefore targets `http://localhost:3000`, which is
  [a deployment you run yourself](/guides/self-host).

  Point the CLI at your own deployment with `myrqen config set-url http://localhost:3000`, or
  per command with `MYRQEN_API_BASE_URL`.
</Warning>

| URL                     | Status                                                                                                   |
| ----------------------- | -------------------------------------------------------------------------------------------------------- |
| `http://localhost:3000` | A [deployment you run yourself](/guides/self-host). Use this.                                            |
| `https://api.myrqen.cc` | The CLI's shipped default and the intended hosted API. **Not deployed.**                                 |
| `https://myrqen.cc`     | The intended canonical application origin — dashboard, share viewer, and the same API. **Not deployed.** |

When a deployment does answer on more than one hostname, `apps/web/proxy.ts` decides what
happens: the API hostname serves `/api/*` and nothing else, and anything else on it is
redirected to the canonical host with a 308. `/api/v1/health`, `/api/v1/ready`, and
`/.well-known/*` answer on **any** hostname, because a health check asked of a specific
hostname must not be redirected.

## Conventions

<AccordionGroup>
  <Accordion title="JSON in, JSON out">
    Requests and responses are `application/json`, except the export endpoints, which
    return `text/html`, `text/markdown`, or `application/json` as an attachment, and the
    live-progress endpoint, which returns `text/event-stream`.
  </Accordion>

  <Accordion title="Idempotency where retries are normal">
    `POST /api/v1/reports` is idempotent on `localReportId` — a retry reuses the same quota
    reservation and returns 200 instead of 201. `POST /api/v1/projects` is idempotent on
    `bindingPublicId`.
  </Accordion>

  <Accordion title="No pagination">
    There is no cursor or page parameter anywhere in `/api/v1`. Collection endpoints —
    workspaces, projects, and a report's shares — return the whole set.
  </Accordion>

  <Accordion title="Nothing is cacheable">
    Every API response carries `cache-control: private, no-store, must-revalidate`. Share
    pages under `/s/*` do too, so a report projection is never cached under a key that
    omits the viewer. The only exception is the signed update manifest, which is public and
    cached for 5 minutes.
  </Accordion>

  <Accordion title="Errors are a stable envelope">
    One shape, with a stable `code` to branch on and a `requestId` for correlating with
    server logs. See [Errors](/api-reference/errors).
  </Accordion>

  <Accordion title="Timestamps are ISO 8601 UTC">
    Quota windows are UTC-anchored: the day runs 06:00 UTC to 06:00 UTC, the week runs
    Monday 06:00 UTC to Monday 06:00 UTC. Never derived from a locale or from daylight
    saving.
  </Accordion>
</AccordionGroup>

## Who calls what

<CardGroup cols={2}>
  <Card title="The CLI, with a device credential" icon="terminal">
    `sync-quota`, `workspaces`, `projects`, `reports` (create, progress, upload-intent,
    finalize), `uploads`, `analytics/events`, `updates/manifest`, and the device-link
    endpoints.
  </Card>

  <Card title="The dashboard, with a browser session" icon="browser">
    `auth/*`, `device-links/{id}/approve`, reading and exporting reports, the live event
    stream, and sharing.
  </Card>

  <Card title="Anyone with a share link" icon="share-nodes">
    `shares/slug/{slug}/report` and `shares/slug/{slug}/export/{format}` — optionally with a
    session cookie and a link password. Everything else about the report stays invisible.
  </Card>

  <Card title="Nobody in particular" icon="globe">
    `health`, `ready`, `device-links` (bootstrap), `device-links/{id}/status` and
    `/exchange`, `auth/*`, and `updates/manifest`.
  </Card>
</CardGroup>

## Request limits

| Surface                      | Limit                              |
| ---------------------------- | ---------------------------------- |
| Any JSON route               | 1 MiB body                         |
| Report body upload           | `MAX_REPORT_BYTES`, default 12 MiB |
| Progress events per request  | 25                                 |
| Analytics events per request | 50                                 |

A declared `Content-Length` over the limit is refused before a byte is read; a chunked body
that lies about its size is refused mid-stream and the remainder is never buffered. An
over-limit body answers HTTP **413** with code `BAD_REQUEST` — the wire contract has no
payload-too-large code yet.

## Rate limits

Every throttled surface and its budget is listed in
[Error codes](/reference/error-codes#rate-limits). Two things worth knowing up front:

* Login and recovery throttles are keyed on the network **and** the account, because a
  caller who rotates `X-Forwarded-For` has no trustworthy network identity to be throttled
  by. `TRUSTED_PROXY_HOPS` is what makes the network half meaningful at all.
* Without `REDIS_URL`, counters are process-local — so N replicas allow N times each limit.

## Webhooks

Myrqen does not send outbound webhooks.

There is one **inbound** webhook, for the payment provider, but it is operator-only and is
not documented here. If you are configuring payments on your own deployment, see
[Self-host](/guides/self-host#payments-optional).

## What is not documented here

Two families of endpoint exist in the application and are deliberately withheld from this
reference, because no ordinary user or CLI ever calls them:

| Family              | Why it is withheld                                                                                                                                                    |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/api/v1/admin/*`   | Operator-only. Aggregated funnel and scan metrics, client-version governance, and audited break-glass access to a customer's report body. Requires `isPlatformAdmin`. |
| `/api/v1/billing/*` | Operator- and provider-facing. Checkout, customer portal, and the provider webhook. Inert unless the deployment is configured for payments.                           |

Running your own deployment and need them? Read the route handlers under
`apps/web/app/api/v1/admin` and `apps/web/app/api/v1/billing` — they carry the reasoning in
comments. The [`SUPPORT_GRANT_REQUIRED`](/reference/error-codes#platform-support) error code
is still documented, because a self-hosted operator can encounter it.

## Next

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/api-reference/authentication">
    Device credentials, browser sessions, and share passwords.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/api-reference/errors">
    The envelope, the codes, and how to branch on them.
  </Card>
</CardGroup>
