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

# Publish an artifact

> Create HTML, Markdown, and JSX artifacts from the CLI, REST API, or MCP.

Publishing creates an artifact and its first immutable version. Updating it later appends more versions without changing the earlier snapshots.

## Pick a surface

Use whichever surface matches who (or what) is publishing:

| You are...                  | Use                                            |
| --------------------------- | ---------------------------------------------- |
| A human in the browser      | [Web dashboard](/surfaces/web)                 |
| A local coding agent        | [CLI](/surfaces/cli)                           |
| A backend service or CI job | [REST API](/surfaces/rest-api) with an API key |
| An MCP-capable agent        | [MCP tools](/surfaces/mcp)                     |

## Create an artifact

The fastest path from a local file to a durable URL is the CLI's `push`. The REST and MCP equivalents take the same fields explicitly.

<CodeGroup>
  ```bash CLI theme={"theme":"github-dark"}
  artifacts push --owner alice --project-slug default --file ./report.md
  ```

  ```bash REST theme={"theme":"github-dark"}
  curl -X POST "$API_URL/api/artifacts" \
    -H "authorization: Bearer $TOKEN" \
    -H "content-type: application/json" \
    -d '{
      "ownerUsername": "alice",
      "projectSlug": "default",
      "slug": "launch-review",
      "type": "md",
      "title": "Launch review",
      "description": "Agent-generated launch notes",
      "content": "# Launch review\n\nReady for review.",
      "changelog": "Initial publish",
      "access": { "publicView": true, "publicEdit": false }
    }'
  ```

  ```json MCP theme={"theme":"github-dark"}
  {
    "tool": "create_artifact",
    "input": {
      "ownerUsername": "alice",
      "projectSlug": "default",
      "slug": "launch-review",
      "type": "md",
      "title": "Launch review",
      "content": "# Launch review\n\nReady for review.",
      "access": { "publicView": true, "publicEdit": false }
    }
  }
  ```
</CodeGroup>

### What `push` infers

`push` is built for speed — it fills in everything it can from the file:

* **Type** from the file extension: `.md`, `.markdown`, `.html`, `.htm`, `.jsx`, `.tsx`.
* **Title** from the Markdown heading, or the file name.
* **Slug** from the title.
* **Access** as public view, private edit.

Override any of it when you need to:

```bash theme={"theme":"github-dark"}
artifacts push \
  --owner alice \
  --project-slug default \
  --file ./prototype.tsx \
  --type jsx \
  --title "Prototype v1" \
  --slug prototype-v1 \
  --private
```

<Tip>
  Use `--ensure` when an agent should reuse an existing artifact instead of failing on a slug conflict:

  ```bash theme={"theme":"github-dark"}
  artifacts push --owner alice --project-slug default --file ./report.md --ensure
  ```
</Tip>

### REST fields

For `POST /api/artifacts`, these fields are **required**: `projectSlug`, `slug`, `type`, `title`, `content`, and `access`. `ownerUsername` is **optional** — when omitted, the API infers the owner from the authenticated credential (the signed-in user, or the account an API key / agent token was issued for). Pass it only to publish into another account you can access. The `description` and `changelog` fields are also optional.

### Publish into a workspace

When you already have a workspace ID, post to the workspace route instead. The body is the same, minus `ownerUsername` (the workspace is already selected):

```text theme={"theme":"github-dark"}
POST /api/workspaces/:workspaceId/artifacts
```

## Update an artifact

Appending a version needs only the artifact ID and new content.

<CodeGroup>
  ```bash CLI theme={"theme":"github-dark"}
  artifacts artifact update \
    --artifact-id ARTIFACT_ID \
    --json '{"content":"# Launch review\n\nUpdated after QA.","changelog":"QA edits"}'
  ```

  ```bash REST theme={"theme":"github-dark"}
  curl -X POST "$API_URL/api/artifacts/$ARTIFACT_ID/versions" \
    -H "authorization: Bearer $TOKEN" \
    -H "content-type: application/json" \
    -d '{"content":"# Launch review\n\nUpdated after QA.","changelog":"QA edits"}'
  ```

  ```json MCP theme={"theme":"github-dark"}
  {
    "tool": "update_artifact",
    "input": {
      "artifactId": "ARTIFACT_ID",
      "content": "# Launch review\n\nUpdated after QA.",
      "changelog": "QA edits"
    }
  }
  ```
</CodeGroup>

<Warning>
  For concurrent writers, include `expectedLatestVersion` in REST or MCP requests. If the head has moved on, the API returns a conflict instead of silently overwriting another actor's work.
</Warning>

## Check a slug before you publish

Avoid surprises by checking availability and previewing the final URL first:

```bash theme={"theme":"github-dark"}
artifacts artifact slug-availability \
  --owner alice \
  --project-slug default \
  --slug launch-review

artifacts artifact url-preview \
  --owner alice \
  --project-slug default \
  --slug launch-review
```
