# API Reference

Markdown + Mermaid.js Renderer provides a REST API for creating, reading, updating, and deleting shared Markdown documents. This API is designed for AI agents and programmatic clients, but works with any HTTP client.

**Base URL:** `https://markdown.pikselimaa.fi/api`

## Authentication

There is no authentication. Access is controlled entirely through document tokens (22-character base64url strings). The token is the key — anyone with the token can read, update, or delete the document.

## Endpoints

### GET /api/health

Health check endpoint. Returns 200 with a status message.

```bash
curl https://markdown.pikselimaa.fi/api/health
```

**Response:**

```json
{
  "status": "ok"
}
```

### GET /api/config

Returns the server's configuration: default retention period and allowed range.

```bash
curl https://markdown.pikselimaa.fi/api/config
```

**Response:**

```json
{
  "defaultRetentionDays": 15,
  "minRetentionDays": 1,
  "maxRetentionDays": 365
}
```

### POST /api/documents

Create a new shared Markdown document. Returns a 22-character token and a shareable URL.

```bash
curl -X POST https://markdown.pikselimaa.fi/api/documents \
  -H 'Content-Type: application/json' \
  -d '{
    "content": "# My Document\n\nHello, **world**!\n\n```mermaid\nflowchart LR\n  A --> B\n```",
    "retentionDays": 30
  }'
```

**Request body:**

| Field | Type | Required | Description |
|---|---|---|---|
| `content` | string | Yes | Markdown text (max 512 KB). Must not be empty or whitespace-only. |
| `retentionDays` | integer | No | How long the document persists before automatic expiry. Range: 1–365. Default: 15 days. |

**Response (201 Created):**

```json
{
  "token": "QZbaNMoSOZGoLB_wOu8Y1w",
  "content": "# My Document\n\nHello, **world**!",
  "retentionDays": 30,
  "createdAt": "2026-08-06T12:00:00.000Z",
  "updatedAt": "2026-08-06T12:00:00.000Z",
  "expiresAt": "2026-09-05T12:00:00.000Z",
  "url": "https://markdown.pikselimaa.fi/v/QZbaNMoSOZGoLB_wOu8Y1w"
}
```

**Error responses:**

| Status | Meaning |
|---|---|
| 400 | Invalid request body (missing content, retentionDays out of range, or unknown fields) |
| 413 | Content exceeds 512 KB |

### GET /api/documents/:token

Fetch a shared document by its token.

```bash
curl https://markdown.pikselimaa.fi/api/documents/QZbaNMoSOZGoLB_wOu8Y1w
```

**Response (200 OK):**

```json
{
  "token": "QZbaNMoSOZGoLB_wOu8Y1w",
  "content": "# My Document\n\nHello, **world**!",
  "retentionDays": 30,
  "createdAt": "2026-08-06T12:00:00.000Z",
  "updatedAt": "2026-08-06T12:00:00.000Z",
  "expiresAt": "2026-09-05T12:00:00.000Z",
  "url": "https://markdown.pikselimaa.fi/v/QZbaNMoSOZGoLB_wOu8Y1w"
}
```

**Error responses:**

| Status | Meaning |
|---|---|
| 404 | Document not found, deleted, or expired |

### PUT /api/documents/:token

Update a shared document. You can update the content, the retention period, or both.

```bash
curl -X PUT https://markdown.pikselimaa.fi/api/documents/QZbaNMoSOZGoLB_wOu8Y1w \
  -H 'Content-Type: application/json' \
  -d '{
    "content": "# Updated Document\n\nNew content here.",
    "retentionDays": 60
  }'
```

**Request body:**

| Field | Type | Required | Description |
|---|---|---|---|
| `content` | string | At least one of `content` or `retentionDays` | New Markdown text (max 512 KB). |
| `retentionDays` | integer | At least one of `content` or `retentionDays` | New retention period in days (1–365). Resets the expiry timer from now. |

**Response (200 OK):**

```json
{
  "token": "QZbaNMoSOZGoLB_wOu8Y1w",
  "content": "# Updated Document\n\nNew content here.",
  "retentionDays": 60,
  "createdAt": "2026-08-06T12:00:00.000Z",
  "updatedAt": "2026-08-06T13:00:00.000Z",
  "expiresAt": "2026-10-05T13:00:00.000Z",
  "url": "https://markdown.pikselimaa.fi/v/QZbaNMoSOZGoLB_wOu8Y1w"
}
```

**Error responses:**

| Status | Meaning |
|---|---|
| 400 | Invalid request body (retentionDays out of range, or neither content nor retentionDays provided) |
| 404 | Document not found |
| 413 | Content exceeds 512 KB |

### DELETE /api/documents/:token

Soft-delete a shared document. The token becomes invalid immediately. The actual database row is purged after 24 hours.

```bash
curl -X DELETE https://markdown.pikselimaa.fi/api/documents/QZbaNMoSOZGoLB_wOu8Y1w
```

**Response (204 No Content):** No body.

**Error responses:**

| Status | Meaning |
|---|---|
| 404 | Document not found or already deleted |

## AI Agent Workflow

The typical collaboration flow between an AI agent and a human user:

1. **Agent creates** a document: `POST /api/documents` with initial content
2. **Agent sends the URL** to the human (from the `url` field in the response)
3. **Human opens the URL** — the document loads in the browser with editor + live preview
4. **Both can iterate** — the agent `PUT` updates the content, the human edits in the browser (edits auto-save)
5. **Human can delete** — the `DELETE` endpoint makes the link invalid immediately
6. **Document expires** — after the retention period, the document is automatically removed

## Rate limiting

| Operation | Limit |
|---|---|
| POST / PUT / DELETE | 30 requests per minute per IP |
| GET | 120 requests per minute per IP |

Requests exceeding these limits receive HTTP 429 Too Many Requests.

## Content limits

- Maximum content size: **512 KB** per document (measured as UTF-8 byte length)
- Maximum retention period: **365 days**
- Minimum retention period: **1 day**

## Error format

All error responses return JSON:

```json
{
  "error": "description of the error"
}
```

For validation errors (400), the response also includes an `issues` array with field-level details:

```json
{
  "error": "validation failed",
  "issues": [
    { "path": ["content"], "message": "content is required" }
  ]
}
```
