# Create or upsert post

> Create a draft or published post, or upsert by slug with an account API key.

HTML version: https://blogizi.com/docs/api-create-post
Markdown version: https://blogizi.com/docs/api-create-post.md

Primary write endpoint for the CLI and Obsidian plugin. Project is selected via `X-Blogizi-Project`, body fields, or automatically when the account has exactly one project. See [Authentication](/docs/api-authentication).

## Request

```http
POST /api/posts
Authorization: Bearer YOUR_ACCOUNT_API_KEY
X-Blogizi-Project: your-project-slug
Content-Type: application/json
```

```json
{
  "title": "How we built our auth flow",
  "slug": "how-we-built-our-auth-flow",
  "description": "≤160 char meta description",
  "keyword": "indie app authentication",
  "content": "Markdown body…",
  "status": "draft",
  "upsert": false
}
```

## Fields

- `title`, `slug` — required
- `description`, `keyword`, `content` — optional but recommended for SEO
- `status` — `draft` or `published`
- `upsert` — when `true`, update an existing post with the same slug (Obsidian plugin pattern). Default create fails if the slug already exists.
- `projectSlug` / `project` / `projectId` — optional if the header or sole-project rule already selects a blog

## Response

Returns the post payload plus `{ project: { id, slug }, created: boolean }`. Status is `201` on create and `200` on upsert update.

> Prefer [CLI publishing](/docs/cli-publishing) for local markdown files. Use this endpoint when building your own client or when the Obsidian plugin upserts by slug.
