<!-- Agent rule: this folder is served at /ai. Keep it true to the code; AiDocsTest checks every /api/v1 route is in api-reference.md. -->
# content.puzzlik.com — publishing API for short vertical videos

Publish one vertical video (a chess short) to **YouTube Shorts, Instagram Reels and TikTok** with one API.
The API is wire-compatible with the part of Publora's API that reels uses (same paths and field names).

- Base URL: `https://content.puzzlik.com/api/v1`
- Auth: header `x-publora-key: sk_live_…` on every `/api/v1` call (also accepted: `x-api-key`, `Authorization: Bearer`).
  Keys are created by a human in `https://content.puzzlik.com/admin`. Never print a key; mask it as `sk_l…(56 chars)`.
- Bodies: JSON. Every 2xx response is JSON with `"success": true`. Errors: `{"success": false, "error": "…", "code": "…", "field"?: "…"}`.
- Times: ISO 8601 UTC with milliseconds, e.g. `2026-11-07T14:02:00.000Z`. Any offset is accepted on input.
- Only a human can connect accounts (OAuth in `/admin`). Agents use `GET platform-connections` to find `platformId`s.

## Docs

| Doc | Read it for |
|---|---|
| [quickstart.md](https://content.puzzlik.com/ai/quickstart.md) | the whole flow in 6 calls, with curl |
| [api-reference.md](https://content.puzzlik.com/ai/api-reference.md) | every endpoint, request and response |
| [platform-settings.md](https://content.puzzlik.com/ai/platform-settings.md) | `platformSettings` per platform, and the video rules |
| [statuses.md](https://content.puzzlik.com/ai/statuses.md) | group and per-platform statuses, how to poll, `postedId`/`permalink` |
| [errors.md](https://content.puzzlik.com/ai/errors.md) | every error code and what to do about it |
| [idempotency.md](https://content.puzzlik.com/ai/idempotency.md) | `Idempotency-Key`, and how to never post twice |

## Rules an agent must follow

1. **Never publish twice.** Send an `Idempotency-Key` on `create-post` and on `update-post {"publishNow": true}`, derived from your own job id, and reuse it on retries. A public post can't be taken back.
2. **Check before acting.** Call `get-post` and only send `publishNow` when the group is `draft`.
3. **Instagram has no private posts.** Test with YouTube `privacy: "private"` and TikTok `viewerSetting: "SELF_ONLY"`, leave Instagram out of tests.
4. Publishing is asynchronous: `publishNow` returns at once with status `processing`. Poll `get-post` every 15–60 s; it takes 30–120 s.
5. If a connection is `reconnect_required`, tell the human to reconnect it in `https://content.puzzlik.com/admin`. Don't retry.

Health: `GET https://content.puzzlik.com/health`. This index is also at `https://content.puzzlik.com/llms.txt`.
