---
title: "Create a blog post draft (admin-only)"
method: POST
path: "/api/v1/blog/posts"
tags: ["Blog"]
---

# Create a blog post draft (admin-only)

`POST /api/v1/blog/posts`

## Request

- Base URL: `https://investormatch.pro`
- URL: `https://investormatch.pro/api/v1/blog/posts`
- Auth: HTTP bearer

ADMIN-ONLY, FREE, AND UNMETERED. Requires an API key owned by an admin; any other valid key receives 403. This endpoint does NOT consume credits, does NOT count against any quota, and has NO rate limit. Posts are always created as DRAFTS and are never auto-published — an admin reviews and publishes them from the dashboard. Creating a draft is the ONLY programmatic blog action; there are no list/edit/delete/publish API endpoints.

## Request body

- BlogPostRequest: Create a blog post DRAFT. Field names are snake_case. HTML in `content` is sanitized server-side to a safe subset of tags. Posts are always created as drafts and never auto-published. Do not send `status` (or set it to "draft"). The article body must meet the GEO content standard or the request is rejected with 400 and nothing is saved: - Any article of 800+ words must be broken into at least 5 <h2> sections (the FAQ heading counts as one). - Every article must end with an <h2>Frequently Asked Questions</h2> section containing 3-5 Q&As, each question in an <h3> and each answer in the <p> that follows it. - Every FAQ answer must be at least 40 characters — a full self-contained sentence an answer engine can quote. - Every statistic or data claim (a percentage, a dollar figure, a ratio, a median/average) must carry an inline source citation in the same sentence: a link to the source, "according to <publication>", or a "(Source: Publication, Year)" parenthetical. - Numbers inside double quotes are read as illustrative examples (a sample founder script, say) and are exempt from the citation rule — do not use quotes to smuggle a real claim past it. - FAQPage JSON-LD is generated automatically from the on-page FAQ section — do not hand-write a schema block; it will be ignored and can conflict with the generated one.
  - `title` string, required
  - `content` string, required: Article HTML. Sanitized server-side; <h1> demoted to <h2>. Must carry at least 5 <h2> sections once it reaches 800 words, a closing "<h2>Frequently Asked Questions</h2>" section of 3-5 <h3>question</h3><p>answer</p> pairs (the FAQPage JSON-LD is generated from it), and an inline source citation on every statistic.
  - `excerpt` string
  - `slug` string: Optional. Auto-generated from the title if omitted.
  - `meta_title` string
  - `meta_description` string
  - `category` string
  - `tags` string[]
  - `featured_image` string: Optional. Must be a valid http(s) URL.
  - `featured_image_alt` string
  - `og_image` string: Optional. Must be a valid http(s) URL.
  - `author_name` string
  - `author_title` string
  - `author_bio` string
  - `ai_prompt` string

## Response `201`

Draft created.

- BlogPostResponse
  - `success` boolean
  - `id` integer
  - `slug` string
  - `status` string
  - `message` string
  - `preview_url` string, uri

## Other responses

- `400`: Invalid payload, non-draft status requested, empty content after sanitization, a non-http(s) image URL, or an article that fails the GEO content standard. GEO failures include `requirements` (the rules) and `details` (an array of { code, message, detail }) so the article can be corrected and resubmitted.
- `401`: Missing or invalid API key.
- `403`: The key is valid for the deck/campaign API but is not owned by an admin, so it is not authorized to publish blog posts.

---

[API](https://skmtc.dev/investormatch/apis/investormatch-pro-api.md) · [All operations](https://skmtc.dev/investormatch/apis/investormatch-pro-api/llms.txt) · [OpenAPI document](https://skmtc.dev/investormatch/apis/investormatch-pro-api/revisions/647f22300043?raw)
