# Publish template

`POST https://postcraft.io/api/v1/templates/{id}/publish`

Promotes the draft to the published copy, changing what `/render` serves. Publishing a template with no unpublished changes succeeds and reports `published: false`, so a caller never has to check first. Bearer tokens must match the template and must not be readonly.

## Authentication

Send one of these headers:

- `x-api-key: <key>`: Long-lived account credential. Create one from the dashboard.
- `Authorization: Bearer <token>`: Short-lived presigned token scoped to a single template (minted via /presigned-url).

## Parameters

| Name | In | Type | Required | Description |
| ---- | -- | ---- | -------- | ----------- |
| `id` | path | string | yes |  |

## Responses

### 200

Publish applied, or nothing to publish.

| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `publishedAt` | string | yes | When the published copy last changed. |
| `updatedAt` | string | yes |  |
| `published` | boolean | yes | False when there were no unpublished changes to publish. |

### Errors

Every error answers with `{ "error": { "code": string, "message": string } }`.

| Status | Meaning |
| ------ | ------- |
| 400 | Invalid input. |
| 401 | Missing or invalid credential. |
| 403 | Authenticated but not allowed. |
| 404 | Not found. |
| 413 | Payload exceeds size limit. |
| 422 | Template render failed. |
| 429 | Rate limited. |

The whole API as an OpenAPI document: https://postcraft.io/api/v1/openapi.json
