Publishing Your First Document via the API

A technical walkthrough of the POST /v1/publish endpoint


Publishing Your First Document via the API

Publishing on lightpaper.org means sending one HTTP request. There's no dashboard to navigate, no settings page to configure, and no deployment to trigger. This walkthrough covers everything you need to know about the POST /v1/publish endpoint.

Prerequisites

You need an API key. Get one by authenticating via email OTP or LinkedIn OAuth (see Authentication Without Passwords). API keys are prefixed with lp_free_, lp_live_, or lp_test_ depending on your account tier.

The Request

Send a POST to https://lightpaper.org/v1/publish with your API key in the X-API-Key header:

curl -X POST https://lightpaper.org/v1/publish \
  -H "Content-Type: application/json" \
  -H "X-API-Key: lp_free_yourkey" \
  -d '{
    "title": "My First Document",
    "content": "# Introduction\n\nYour markdown content here...",
    "format": "post"
  }'

Required Fields

Field Type Description
title string Document title (1-500 characters)
content string Markdown content (1-500,000 characters, minimum 300 words)

Optional Fields

Field Type Default Description
subtitle string null Subtitle displayed below the title
format string "post" One of: "post", "essay", "paper"
authors array [] List of {"name": "...", "handle": "..."} objects
tags array [] Up to 50 string tags for categorization
metadata object {} Arbitrary key-value metadata (max 50KB serialized)
options.slug string auto Custom URL slug (max 80 characters)
options.listed boolean true Whether the document appears in search and feeds
options.og_image string "auto" Open Graph image setting

Content Requirements

Your content must meet two requirements:

  1. Minimum 300 words — shorter content returns a 422 error
  2. At least one heading — the content must contain at least one line starting with #

These requirements ensure that every published document has enough substance to be useful and enough structure to be navigable.

The Response

A successful publish returns a 201 status with detailed feedback:

{
  "id": "doc_a1b2c3d4",
  "url": "https://lightpaper.org/my-first-document",
  "permanent_url": "https://lightpaper.org/d/doc_a1b2c3d4",
  "version": 1,
  "created_at": "2026-03-04T12:00:00Z",
  "word_count": 847,
  "reading_time_minutes": 4,
  "content_hash": "sha256:abc123...",
  "quality_score": 68,
  "quality_breakdown": {
    "structure": 22,
    "substance": 14,
    "tone": 18,
    "attribution": 14
  },
  "quality_suggestions": [
    "Add a References section"
  ],
  "author_gravity": 1,
  "author_gravity_badges": ["linkedin"],
  "gravity_note": "Verify your domain to reach Gravity 2."
}

Two URLs

Every document gets two URLs:

Both URLs support content negotiation. Browsers and crawlers get HTML. Clients sending Accept: application/json get the raw document data.

Slug Generation

If you don't specify a custom slug, one is generated from your title:

Slugs are automatically deduplicated. If my-first-document already exists, the system generates my-first-document-2.

Certain slugs are reserved to prevent conflicts with platform routes: api, login, search, feed, sitemap, and others. Attempting to use a reserved slug returns a 422 error.

Versioning

Every publish creates version 1. Subsequent updates via PUT /v1/documents/{id} create new versions. The system stores up to 100 versions per document. Each version records the content hash, word count, and reading time, giving you a full history of changes.

Using Python

Here's a complete example using httpx:

import httpx

response = httpx.post(
    "https://lightpaper.org/v1/publish",
    headers={"X-API-Key": "lp_free_yourkey"},
    json={
        "title": "My First Document",
        "subtitle": "A quick test of the API",
        "content": "# Introduction\n\nThis is my first document...",
        "format": "post",
        "authors": [{"name": "Your Name", "handle": "yourhandle"}],
        "tags": ["test", "first-post"],
    },
)
print(response.json())

What Happens After Publishing

Once your document is live, several things happen automatically:

  1. Search engine notification: IndexNow pings Bing, DuckDuckGo, Yandex, and Seznam with your new URLs. Google receives a sitemap ping.
  2. Feed inclusion: If listed and quality >= 40, your document appears in the Atom feed.
  3. Sitemap update: The sitemap regenerates to include your document.
  4. OG image generation: A social sharing image is created at /og/{doc_id}.png.

No manual steps required. Your content is discoverable the moment it's published.

Error Handling

Common errors and their meanings:

Status Error Fix
401 Invalid API key Check your X-API-Key header
413 Request too large Content exceeds 2MB body limit
422 Under 300 words Add more content
422 No headings Add at least one # heading
422 Reserved slug Choose a different custom slug
429 Rate limited Max 60 publishes per hour

References