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

# API Overview

> Base URL, authentication, pagination, rate limiting, and API guarantees.

## Base URL

```
https://api.artifacta.io
```

All endpoints (except `GET /health`) are prefixed with `/v1/`.

API-direct transcript storage uses the existing artifact metadata and content-type fields,
not a new REST field. See the multipart, JSON-body, and list recipes in the
[session transcript guide](/guides/transcripts).

Model provenance likewise uses existing metadata keys (`model`, `model_source`,
`models_used`) — there is no new REST field. See
[model capture](/guides/transcripts#model-capture).

## Authentication

Every request requires a Bearer token:

```bash theme={null}
Authorization: Bearer ak_live_<key>
```

Get your key from [app.artifacta.io/dashboard/keys](https://app.artifacta.io/dashboard/keys). Use `GET /v1/whoami` to verify your key.

## Endpoints

### Artifacts

| Method | Endpoint | Description |
| - | - | - |
| `POST` | [`/v1/artifacts`](/api/upload-artifact) | Upload an artifact |
| `GET` | [`/v1/artifacts`](/api/list-artifacts) | List artifacts with filters |
| `GET` | [`/v1/artifacts/{id}`](/api/get-artifact) | Get artifact metadata |
| `GET` | [`/v1/artifacts/{id}/download-url`](/api/download-url) | Get presigned download URL |
| `DELETE` | [`/v1/artifacts/{id}`](/api/delete-artifact) | Soft-delete an artifact |
| `POST` | [`/v1/artifacts/{id}/links`](/api/create-link) | Create a download link |

### Presigned uploads

| Method | Endpoint | Description |
| - | - | - |
| `POST` | [`/v1/artifacts/upload-url`](/api/presigned-upload) | Get presigned upload URL (large files) |
| `POST` | [`/v1/artifacts/{id}/complete`](/api/complete-upload) | Finalize presigned upload |

### Artifact Pages (authenticated)

| Method | Endpoint | Description |
| - | - | - |
| `POST` | [`/v1/artifacts/{id}/publish`](/api/publish-artifact) | Publish an artifact as a public page |
| `DELETE` | [`/v1/artifacts/{id}/publish`](/api/unpublish-artifact) | Unpublish a page (accepts artifact ID or page slug) |

### Artifact Pages (public — no auth)

| Method | Endpoint | Description |
| - | - | - |
| `GET` | [`/v1/public/pages/{slug}/gate-info`](/api/gate-info) | Check if a page is password-protected |
| `POST` | [`/v1/public/pages/{slug}/unlock`](/api/unlock-page) | Verify passcode, receive a content token |
| `POST` | [`/v1/public/pages/{slug}/report`](/api/report-page) | Submit an abuse report (always 202) |

<Info>
  The three `/v1/public/pages/` endpoints require **no Bearer token**. They are called by the public viewer and by end users' browsers. The "Every request requires a Bearer token" rule applies only to authenticated endpoints.
</Info>

### Sessions

| Method | Endpoint | Description |
| - | - | - |
| `POST` | [`/v1/sessions/{id}/seal`](/api/seal-session) | Seal a session |

### Account

| Method | Endpoint | Description |
| - | - | - |
| `GET` | [`/v1/whoami`](/api/whoami) | Verify auth, get tenant info |
| `GET` | [`/health`](/api/health) | Health check (no auth) |

## Content upload paths

| Method | Best for | Size limit |
| - | - | - |
| Multipart form data (`POST /v1/artifacts`) | CLI, file uploads | 500 MB |
| JSON body with base64 (`POST /v1/artifacts`) | Programmatic callers, small content | 10 MB decoded |
| Presigned URL (`upload-url` → PUT → `complete`) | Large files | 5 GB |

## Pagination

All list endpoints use **cursor-based pagination**.

* Response includes `next_cursor` (`null` if no more results)
* Pass `cursor=<value>` for the next page
* Max `limit`: 200, default: 50

<Info>
  **Sort order guarantee:** Results are always ordered by `created_at DESC, artifact_id DESC`. This is a V1 API contract and will not change without a new API version.
</Info>

## Rate limiting

Per-tenant: **100 requests/second sustained, 200 requests/second burst** (sliding window).

**Headers on every response:**

| Header | Description |
| - | - |
| `X-RateLimit-Limit` | Requests per second allowed |
| `X-RateLimit-Remaining` | Remaining in current window |
| `X-RateLimit-Reset` | Unix timestamp when window resets |

When exceeded: `429 Too Many Requests` with `Retry-After` header and `retry_after_seconds` in the body.

## Error response shape

All errors return:

```json theme={null}
{
  "error": {
    "code": "artifact_not_found",
    "message": "Artifact art_xxx was not found.",
    "status": 404
  }
}
```

Match on `error.code` (stable). Never parse `error.message`. See the [full error reference](/errors).

## The `page` field on artifact responses

`GET /v1/artifacts/{id}` includes a `page` sub-object when the artifact has a live published page:

```json theme={null}
{
  "artifact_id": "art_abc123",
  "filename": "report.pdf",
  "page": {
    "public_url": "https://artifacta.io/a/pg_aB3xK9mP1qR5sT2u",
    "visibility": "unlisted"
  }
}
```

| Field | Type | Description |
| - | - | - |
| `page.public_url` | string | Full viewer URL. Anyone with this URL can view the artifact. |
| `page.visibility` | string | `"unlisted"` or `"public"`. |

`page` is `null` when no live page exists (never published, or unpublished). It is present only on the single-artifact `GET /v1/artifacts/{id}` response — list results always return `page: null`.

## API guarantees

* **Read-after-write consistency:** An artifact written via `POST /v1/artifacts` is immediately visible to all read endpoints.
* **Backward compatibility:** Additive changes (new fields, new optional parameters, new endpoints) are non-breaking. Removals and type changes require a new API version. V1 remains available for 12 months after V2 launches.

<Note>
  **Coming in V1.1:** `POST /v1/artifacts/batch/download-urls` — batch download URLs for up to 20 artifacts in a single request.
</Note>


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