---
title: "Create a report"
method: POST
path: "/reports"
tags: ["Reports"]
---

# Create a report

`POST /reports`

## Request

- Base URL: `https://commareports.com/api/v1`
- URL: `https://commareports.com/api/v1/reports`
- Auth: HTTP bearer

Upload an HTML report on behalf of the token's owner. Defaults to `visibility: public` with `public_permission: comment` (anyone with the link can read; commenting needs a free sign-in) so the returned share URL works out of the box; pass `visibility: private` to keep it unlisted (link permission is then forced to `none`). Optional inline `assets` are uploaded and relative references in the HTML (src/href/srcset/url(...)) are rewritten to stored URLs. Scope: `reports:write`. Rate limit: per-token sliding window (plan-aware — Free 60 req/min, Pro 600, Team/Enterprise 6000 by default); 429 responses carry a Retry-After header.

## Request body

- ReportCreateRequest
  - `html` string, required: Required. Max 5 MB (413 above that).
  - `title` string: Defaults to 'Untitled report'.
  - `description` string
  - `visibility` 'private' | 'registered' | 'public': 'team' and 'domain' cannot be set at create time — use PUT /reports/{id}/share.
  - `public_permission` 'none' | 'view' | 'comment' | 'edit': Link permission for /p/:id. Forced to 'none' when visibility is 'private'.
  - `producer_name` string: Attribution chip on the public view.
  - `producer_url` string, uri: http(s) only; anything else is dropped.
  - `producer_icon_url` string, uri: http(s) only; anything else is dropped.
  - `source_recipe` object: Arbitrary JSON object powering the 'Continue this run' modal (.prompt, .tools).
  - `assets` InlineAssetInput[]: Inline assets; relative references in the HTML are rewritten to stored URLs.
    - `relative_path` string, required: POSIX-style path the HTML references, e.g. 'images/hero.png'. No leading slash, no '.'/'..' segments, no '%', '?' or '#'.
    - `content_base64` string, required: Base64 file contents ('data:' URL prefix tolerated).
    - `content_type` string: MIME type; defaults to application/octet-stream.

## Response `201`

Report created.

- ReportCreated
  - `id` string, uuid, required
  - `title` string, required
  - `created_at` string, date-time, required
  - `edit_url` string, uri, required: Absolute editor URL (/r/:id).
  - `share_url` string, uri, required: Absolute public share URL (/p/:id).
  - `url` string, uri, required: Same as share_url.
  - `assets` UploadedAsset[], required
    - `relative_path` string, required
    - `url` string, uri, required
    - `mime` string, required
    - `size_bytes` integer, required

## Other responses

- `400`: Malformed body or invalid field.
- `401`: Missing, invalid, revoked, or expired token.
- `403`: Token missing the required scope, or no access to the resource.
- `413`: Payload exceeds a size limit (HTML > 5 MB; asset > 25 MB per file or > 250 MB per report).
- `429`: Rate limit exceeded. Rate limit: per-token sliding window (plan-aware — Free 60 req/min, Pro 600, Team/Enterprise 6000 by default); 429 responses carry a Retry-After header.
- `500`: Unexpected server error.

---

[API](https://skmtc.dev/commareports/apis/comma-api.md) · [All operations](https://skmtc.dev/commareports/apis/comma-api/llms.txt) · [OpenAPI document](https://skmtc.dev/commareports/apis/comma-api/revisions/cd5263522ade?raw)
