# Lots.Blog API Documentation

Base URL: `https://api.lots.blog`

## Overview

Blogging and content platform

## Authentication

All API requests require authentication using an API key. Include your API key in the request header:

```bash
curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/endpoint
```

Or using the `X-API-Key` header:

```bash
curl -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/endpoint
```

### Getting an API Key

1. Log in to your account at https://api.lots.blog/dashboard
2. Navigate to the API Keys section
3. Click "Create New API Key"
4. Copy and securely store your API key (it will only be shown once)

## Rate Limiting

API requests are rate-limited to prevent abuse. Default limits:

- **100 requests per minute** per API key
- Rate limit headers are included in all responses:
  - `X-RateLimit-Limit`: Maximum requests allowed
  - `X-RateLimit-Remaining`: Requests remaining in current window
  - `X-RateLimit-Reset`: Time when the rate limit resets

## Response Format

All API responses follow a consistent JSON format:

### Success Response

```json
{
  "success": true,
  "data": {
    // Response data
  },
  "meta": {
    "timestamp": "2025-01-06T00:00:00.000Z"
  }
}
```

### Error Response

```json
{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message"
  },
  "meta": {
    "timestamp": "2025-01-06T00:00:00.000Z"
  }
}
```

## Common Error Codes

| Code | HTTP Status | Description |
|------|-------------|-------------|
| `AUTHENTICATION_REQUIRED` | 401 | API key is missing or invalid |
| `RATE_LIMIT_EXCEEDED` | 429 | Too many requests, slow down |
| `ENDPOINT_NOT_FOUND` | 404 | The requested endpoint does not exist |
| `VALIDATION_ERROR` | 400 | Request parameters are invalid |
| `INTERNAL_ERROR` | 500 | Server error, please try again |

## API Endpoints

Total endpoints: **28**

### content

#### POST /api/v1/lotsblog/blogs/:blog_id/domain/check

Check the owned blog custom domain verification and HTTPS certificate state. Returns exact DNS records and a plain-language next step. Does not change the user DNS records.

**Rate Limit:** 100 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): Blog UUID from list_blogs

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/domain/check
```

---

#### POST /api/v1/lotsblog/blogs/:blog_id/images/complete

Verify the uploaded image size and magic bytes before using it in an article. Call after PUT to the URL returned by create_image_upload. Return a public CDN URL.

**Rate Limit:** 100 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): Blog UUID from list_blogs
- `file_key` (string, **required**): Exact file_key from the upload or list_media result
- `file_size` (integer, **required**): 

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000","file_key":"example_file_key","file_size":1}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/images/complete
```

---

#### POST /api/v1/lotsblog/blogs/:blog_id/domain

Connect the blog owner custom hostname and return exact required CNAME and optional TXT DNS records. Ask the user to set records at their DNS provider, then call check_domain. Owner-only; requires a plan with custom domains. Does not change DNS automatically or replace an existing different domain.

**Rate Limit:** 100 requests/minute

**Request Parameters:**

- `domain` (string, **required**): Hostname only, such as blog.example.com
- `blog_id` (string, **required**): Blog UUID from list_blogs

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"example_domain","blog_id":"00000000-0000-0000-0000-000000000000"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/domain
```

---

#### POST /api/v1/lotsblog/blogs/:blog_id/images/upload

Prepare a local image upload without passing base64 through MCP. Return a 15-minute presigned PUT URL, headers and file_key. PUT the local bytes then call complete_image_upload. JPEG, PNG, WebP or GIF, at most 25 MB. Requires the blog owner plan and create permission. Uploaded images are public.

**Rate Limit:** 100 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): Blog UUID from list_blogs
- `filename` (string, **required**): 
- `file_size` (integer, **required**): Exact file size in bytes
- `mime_type` (string, **required**): 

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000","filename":"example_filename","file_size":1,"mime_type":"example_mime_type"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/images/upload
```

---

#### POST /api/v1/lotsblog/blogs/:blog_id/images/delete

Permanently delete an unused image belonging to this blog, only under the user instruction. Images referenced by article content, covers or blog appearance cannot be deleted.

**Rate Limit:** 100 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): Blog UUID from list_blogs
- `file_key` (string, **required**): Exact file_key from the upload or list_media result

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000","file_key":"example_file_key"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/images/delete
```

---

#### POST /api/v1/lotsblog/blogs/:blog_id/posts/:post_id/quality-check

Optional paid article quality check requested by the user. Charges the blog owner token-based LotsTech Credits for model input and output; cost varies with article length and usage. Set authorize_charge=true for a requested paid quality check; no separate resource funding consent is required. Never guarantees rankings or gates publication. Maximum 45000 characters; unchanged-revision retries reuse execution.

**Rate Limit:** 10 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): 
- `post_id` (string, **required**): 
- `authorize_charge` (boolean, **required**): True when the user requests this paid token-based quality check

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000","post_id":"00000000-0000-0000-0000-000000000000","authorize_charge":true}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/posts/:post_id/quality-check
```

---

#### GET /api/v1/lotsblog/blogs/:blog_id/images

List a bounded page of image keys and CDN URLs for this blog. Use next_cursor to continue. Images uploaded through MCP are publicly accessible.

**Rate Limit:** 100 requests/minute

**Request Parameters:**

- `limit` (integer, optional): 
- `cursor` (string, optional): 
- `blog_id` (string, **required**): Blog UUID from list_blogs

**Example Request:**

```bash
curl -X GET \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/images
```

---

#### POST /api/v1/lotsblog/blogs/:blog_id/posts/:post_id/unpublish

Move a published or scheduled article back to a private draft under user instructions. Clears publication time and any pending schedule. The public URL stops serving the article.

**Rate Limit:** 100 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): Blog UUID from list_blogs
- `post_id` (string, **required**): Post UUID from list_blog_posts

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000","post_id":"00000000-0000-0000-0000-000000000000"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/posts/:post_id/unpublish
```

---

### General

#### GET /api/v1/lotsblog/funding

Check plan coverage, credit funding and current capacity rates. Plan coverage is used first; capacity beyond it is paid from the owner's credits automatically, charged daily (free credits first, then plan credits, then purchased). If credits run low, give the returned settings_url so the owner can top up or choose a plan.

**Rate Limit:** 100 requests/minute

**Request Parameters:**


**Example Request:**

```bash
curl -X GET \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/funding
```

---

#### POST /api/v1/lotsblog/blogs

Create a hosted blog. A plan covers its included blogs; each extra blog costs that plan's own per-blog rate, and without a plan each blog is $9 a month. Capacity is paid from the owner's credits automatically, charged daily. Use get_funding_status for current rates and balance. If credits are insufficient, return the owner settings link so they can top up or choose a plan. Returns the blog and hosting URL.

**Rate Limit:** 30 requests/minute

**Request Parameters:**

- `privacy` (string, optional): Optional. Blog privacy setting. Defaults to 'public'. 'public' = Anyone can view the blog and its posts. 'private' = Only authenticated blog members can view content. Privacy can be changed later via update_blog.
- `blog_name` (string, **required**): REQUIRED. The display name of the blog. This is shown in the blog header, page titles, and admin dashboard. Can contain spaces, special characters, and any UTF-8 characters. Examples: 'My Tech Blog', 'Jane's Photography', 'Acme Corp Blog'.
- `subdomain` (string, **required**): Unique hosted subdomain at https://{subdomain}.lots.blog; 3-63 lowercase letters, numbers or hyphens; cannot start or end with hyphen.

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_name":"example_blog_name","subdomain":"example_subdomain"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs
```

---

#### POST /api/v1/lotsblog/blogs/:blog_id/posts

Create an article with Markdown content, metadata, topics and optional matching supplemental JSON-LD such as FAQPage. Defaults to a private draft. Return preview_url to the user; sign-in is required for draft preview. Publish or schedule only under explicit user instructions. Use list_topics to choose topic_ids.

**Rate Limit:** 30 requests/minute

**Request Parameters:**

- `slug` (string, optional): URL-friendly slug. Must be unique within the blog. Auto-generated from title if not provided. Format: lowercase letters, numbers, hyphens only.
- `title` (string, **required**): Post title. Required for all post types. Used to auto-generate slug if slug not provided.
- `status` (string, optional): Post status. draft=not visible, scheduled=will publish at scheduled_for time, published=live immediately. Default: draft.
- `blog_id` (string, **required**): UUID of the blog where the post will be created. User must be a member of this blog.
- `content` (string, optional): ARTICLE TYPE ONLY: Markdown content for article. Required for post_type=article.
- `post_type` (string, **required**): Type of post to create. Determines which additional fields are required and where data is stored.
- `topic_ids` (array, optional): Topic IDs from list_topics for this blog. On update, omit to preserve or send [] to clear.
- `description` (string, optional): Post summary/snippet text used for previews and metadata. This is not rendered as visible body content on the post page; for listicle introductions, use the first list item instead.
- `source_link` (string, optional): Optional URL to original source or reference for content attribution.
- `reading_time` (integer, optional): ARTICLE TYPE ONLY: Estimated reading time in minutes. Optional.
- `meta_keywords` (array, optional): Array of SEO keywords/tags for search optimization.
- `scheduled_for` (string, optional): ISO 8601 datetime for scheduled publishing. Required if status=scheduled. Must be at least 5 minutes in future.
- `content_format` (string, optional): CONTENT FORMAT: Content rendering format for the post body. Determines how content/list text should be interpreted. Default: markdown.
- `featured_image` (string,null, optional): URL to featured image. Displayed in post previews and social media shares.
- `structured_data` (object,array,null, optional): Optional supplemental JSON-LD structured data for SEO. Object or array is accepted. Do not include Article, NewsArticle, BreadcrumbList, or ItemList because the platform generates those automatically; use this only for matching visible supplemental schema such as FAQPage or HowTo.
- `meta_description` (string, optional): SEO meta description. Shown in search engine results. Recommended: 120-160 characters.

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"example_title","blog_id":"00000000-0000-0000-0000-000000000000","post_type":"example_post_type"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/posts
```

---

#### POST /api/v1/lotsblog/blogs/:blog_id/topics

Create an article topic/category in the selected blog. An explicit slug is preserved and must be unique within that blog; omit it to generate from the name. Returns the numeric topic ID for topic_ids in article create/update.

**Rate Limit:** 30 requests/minute

**Request Parameters:**

- `name` (string, optional): Topic name (required). Used to auto-generate slug if slug not provided.
- `slug` (string, optional): URL-friendly slug. Must be unique within the blog. Auto-generated from name if not provided. Format: lowercase letters, numbers, hyphens only.
- `blog_id` (string, **required**): REQUIRED. UUID of the blog to create the topic in. Call list_blogs to get your blog UUIDs.
- `parent_id` (integer, optional): Optional parent topic ID for creating hierarchical structure (sub-topics). Parent topic must exist in the same blog.
- `meta_title` (string, optional): SEO meta title for the topic page. Supports placeholders: {topicName}, {postCount}, {siteName}.
- `description` (string, optional): Optional description of the topic.
- `meta_keywords` (string, optional): SEO meta keywords for the topic page. Supports placeholders: {topicName}, {postCount}, {siteName}.
- `meta_description` (string, optional): SEO meta description for the topic page. Supports placeholders: {topicName}, {postCount}, {siteName}.

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/topics
```

---

#### DELETE /api/v1/lotsblog/blogs/:blog_id/posts/:post_id

Permanently delete a post and all associated data (articles, list items, polls, comments, likes, etc.). Only owner and admin roles can delete posts. CASCADE constraints will automatically remove all related data. This action cannot be undone.

**Rate Limit:** 20 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): UUID of the blog containing the post.
- `post_id` (string, **required**): UUID of the post to delete permanently.

**Example Request:**

```bash
curl -X DELETE \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/posts/:post_id
```

---

#### DELETE /api/v1/lotsblog/blogs/:blog_id/topics/:topic_id

Delete a topic/category under user instructions. Articles remain intact; their association with this topic is removed. Topics with children must be handled first. Select the numeric topic_id from list_topics.

**Rate Limit:** 20 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): REQUIRED. UUID of the blog. Call list_blogs to get your blog UUIDs.
- `topic_id` (integer, **required**): Numeric topic ID from list_topics

**Example Request:**

```bash
curl -X DELETE \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/topics/:topic_id
```

---

#### GET /api/v1/lotsblog/blogs/:blog_id/analytics

Retrieves traffic and engagement analytics for a blog. IMPORTANT: Requires blog_id — call list_blogs first to get the blog UUID.

**Rate Limit:** 60 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): REQUIRED. UUID of the blog to get analytics for. Call list_blogs to get your blog UUIDs.
- `end_date` (string, optional): End date for analytics period (ISO date: YYYY-MM-DD). Default: today.
- `start_date` (string, optional): Start date for analytics period (ISO date: YYYY-MM-DD). Default: 30 days ago.

**Example Request:**

```bash
curl -X GET \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/analytics
```

---

#### GET /api/v1/lotsblog/blogs/:blog_id

Read the blog, current user role, hosting URL and private Markdown blog_guide. Call list_blogs first to select the blog. Read the guide before writing; it is optional and must not be copied into public articles.

**Rate Limit:** 60 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): REQUIRED. UUID of the blog to retrieve. Call list_blogs to get your blog UUIDs.

**Example Request:**

```bash
curl -X GET \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id
```

---

#### GET /api/v1/lotsblog/blogs/:blog_id/posts/:post_id

Read the saved article and metadata by blog_id and post_id. Call list_blog_posts to find post IDs. Use this to verify saved content and publication status before retrying an uncertain write.

**Rate Limit:** 60 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): UUID of the blog containing the post.
- `post_id` (string, **required**): UUID of the post to retrieve.

**Example Request:**

```bash
curl -X GET \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/posts/:post_id
```

---

#### GET /api/v1/lotsblog/blogs/:blog_id/posts/:post_id/analytics

Read traffic and engagement analytics for an article. Select blog_id from list_blogs and post_id from list_blog_posts. Traffic is not a ranking or AI-citation measurement.

**Rate Limit:** 60 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): REQUIRED. UUID of the blog. Call list_blogs to get your blog UUIDs.
- `post_id` (string, **required**): REQUIRED. UUID of the post to get analytics for. Call list_blog_posts (with a blog_id) to get post UUIDs.

**Example Request:**

```bash
curl -X GET \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/posts/:post_id/analytics
```

---

#### GET /api/v1/lotsblog/blogs/:blog_id/topics/:topic_id

Retrieves details for a specific blog topic. IMPORTANT: Requires blog_id and topic_id — call list_blogs to get the blog UUID, then list_topics to get the topic_id.

**Rate Limit:** 60 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): REQUIRED. UUID of the blog. Call list_blogs to get your blog UUIDs.
- `topic_id` (integer, **required**): Numeric topic ID from list_topics

**Example Request:**

```bash
curl -X GET \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/topics/:topic_id
```

---

#### GET /api/v1/lotsblog/blogs/:blog_id/posts

List all posts for a blog with optional filters by type, status, topic, and pagination. Returns posts ordered by creation date (newest first). Use this to display blog content, filter by draft/published status, or find posts of a specific type.

**Rate Limit:** 60 requests/minute

**Request Parameters:**

- `limit` (integer, optional): Number of posts to return per page. Default: 20, Max: 100.
- `offset` (integer, optional): Number of posts to skip for pagination. Use with limit for paging. Default: 0.
- `status` (string, optional): Filter by post status. If omitted, returns all statuses.
- `blog_id` (string, **required**): UUID of the blog to list posts from. User must be a member of this blog.
- `topic_id` (integer, optional): Numeric topic ID from list_topics
- `post_type` (string, optional): Filter by post type. If omitted, returns all types.

**Example Request:**

```bash
curl -X GET \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/posts
```

---

#### GET /api/v1/lotsblog/blogs

Retrieves all blogs where the authenticated user is an owner or active member. Returns blogs with the user's role in each blog (owner, admin, editor, author, user). This is useful for displaying a blog selector in the UI or for determining which blogs the user can manage. Only active blog memberships are included (status='active' in blog_users table). Blogs are returned with their access URLs (either custom domain or subdomain URL).

**Rate Limit:** 60 requests/minute

**Request Parameters:**


**Example Request:**

```bash
curl -X GET \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/blogs
```

---

#### GET /api/v1/lotsblog/blogs/:blog_id/topics

Lists all topics/categories for a blog. IMPORTANT: Requires blog_id — call list_blogs first to get the blog UUID.

**Rate Limit:** 60 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): REQUIRED. UUID of the blog whose topics to list. Call list_blogs to get your blog UUIDs.
- `parent_id` (integer,null, optional): Filter by parent topic. null = root topics only (no parent), integer = children of that topic, omit = all topics.
- `include_post_count` (boolean, optional): Whether to include post count for each topic. Default: true.

**Example Request:**

```bash
curl -X GET \
  -H "X-API-Key: YOUR_API_KEY" \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/topics
```

---

#### POST /api/v1/lotsblog/blogs/:blog_id/posts/:post_id/publish

Publish the saved post now, only when the user instructs publication. Select blog_id from list_blogs and post_id from list_blog_posts. Returns the saved publication status.

**Rate Limit:** 30 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): REQUIRED. UUID of the blog. Call list_blogs to get your blog UUIDs.
- `post_id` (string, **required**): REQUIRED. UUID of the draft post to publish. Call list_blog_posts (with a blog_id) to get post UUIDs.

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000","post_id":"00000000-0000-0000-0000-000000000000"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/posts/:post_id/publish
```

---

#### POST /api/v1/lotsblog/blogs/:blog_id/posts/:post_id/schedule

Schedule the saved post under the user instructions. Use an ISO 8601 timestamp with timezone, at least five minutes in the future. Select post_id from list_blog_posts. A scheduled status is not confirmation that the article is already live.

**Rate Limit:** 30 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): REQUIRED. UUID of the blog. Call list_blogs to get your blog UUIDs.
- `post_id` (string, **required**): REQUIRED. UUID of the post to schedule. Call list_blog_posts (with a blog_id) to get post UUIDs.
- `scheduled_for` (string, **required**): ISO 8601 datetime when post should be published. Must be at least 5 minutes in the future. Example: 2027-01-15T10:00:00Z

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000","post_id":"00000000-0000-0000-0000-000000000000","scheduled_for":"example_scheduled_for"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/posts/:post_id/schedule
```

---

#### PATCH /api/v1/lotsblog/blogs/:blog_id/posts/:post_id

Update the existing article content, metadata, topics or publication status. Omitted fields are preserved; topic_ids=[] clears topics. Returns preview_url. Use the existing post_id rather than creating a duplicate. Publish or schedule only under user instructions.

**Rate Limit:** 30 requests/minute

**Request Parameters:**

- `slug` (string, optional): New URL slug. Must be unique within blog.
- `title` (string, optional): New post title.
- `status` (string, optional): New status. Changing to published will set published_at to now if not already set.
- `blog_id` (string, **required**): UUID of the blog containing the post.
- `content` (string, optional): ARTICLE TYPE: New markdown content.
- `post_id` (string, **required**): UUID of the post to update.
- `topic_ids` (array, optional): Topic IDs from list_topics for this blog. On update, omit to preserve or send [] to clear.
- `description` (string, optional): New post summary/snippet text used for previews and metadata. This is not rendered as visible body content on the post page; for listicle introductions, use the first list item instead.
- `source_link` (string, optional): New source link.
- `reading_time` (integer, optional): ARTICLE TYPE: New reading time in minutes.
- `meta_keywords` (array, optional): New meta keywords array.
- `scheduled_for` (string, optional): New scheduled publish time.
- `content_format` (string, optional): CONTENT FORMAT: New post rendering format. Changes format metadata for post (and article content when applicable).
- `featured_image` (string,null, optional): New featured image URL. Set to null to remove.
- `structured_data` (object,array,null, optional): Optional supplemental JSON-LD structured data for SEO. Object or array is accepted. Do not include Article, NewsArticle, BreadcrumbList, or ItemList because the platform generates those automatically; use this only for matching visible supplemental schema such as FAQPage or HowTo.
- `meta_description` (string, optional): New meta description.

**Example Request:**

```bash
curl -X PATCH \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000","post_id":"00000000-0000-0000-0000-000000000000"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/posts/:post_id
```

---

#### PATCH /api/v1/lotsblog/blogs/:blog_id

Update the owned blog name, title, privacy or private Markdown blog guide. Only supplied fields change. Use connect_domain/check_domain for custom domains; appearance and team setup use the dashboard.

**Rate Limit:** 30 requests/minute

**Request Parameters:**

- `title` (string, optional): Blog title. Omit to preserve the current title.
- `blog_id` (string, **required**): REQUIRED. UUID of the blog to update. Call list_blogs to get your blog UUIDs.
- `privacy` (string, optional): Optional. Change privacy setting.
- `blog_name` (string, optional): Optional. New display name for the blog.
- `blog_guide` (string, optional): Private optional Markdown audience, voice, facts and writing instructions. Omit to preserve; empty string clears.

**Example Request:**

```bash
curl -X PATCH \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id
```

---

#### PATCH /api/v1/lotsblog/blogs/:blog_id/topics/:topic_id

Update the topic name, description, slug or metadata. Omitted fields are preserved. Supplied slugs are kept and must be unique within the blog. Select topic_id from list_topics.

**Rate Limit:** 30 requests/minute

**Request Parameters:**

- `name` (string, optional): New topic name.
- `slug` (string, optional): New URL slug. Must be unique within blog.
- `blog_id` (string, **required**): REQUIRED. UUID of the blog. Call list_blogs to get your blog UUIDs.
- `topic_id` (integer, **required**): Numeric topic ID from list_topics
- `parent_id` (integer,null, optional): New parent topic ID (integer) or null to make it a root topic. Cannot create circular relationships or set self as parent.
- `meta_title` (string, optional): New SEO meta title.
- `description` (string, optional): New description.
- `meta_keywords` (string, optional): New SEO meta keywords.
- `meta_description` (string, optional): New SEO meta description.

**Example Request:**

```bash
curl -X PATCH \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"00000000-0000-0000-0000-000000000000","topic_id":0}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/topics/:topic_id
```

---

#### POST /api/v1/lotsblog/blogs/:blog_id/images

Upload an image from a public/signed image_url or small image_base64. For a local screenshot or larger image, prefer create_image_upload then complete_image_upload. Return the public CDN URL for featured_image in create_blog_post/update_blog_post or article Markdown. Requires the blog owner active plan and content-create permission; image URLs are public even for private blogs.

**Rate Limit:** 10 requests/minute

**Request Parameters:**

- `blog_id` (string, **required**): REQUIRED. UUID of the blog the image belongs to.
- `filename` (string, optional): Optional human-friendly base name for the stored file (used to build the object key).
- `image_url` (string, optional): Public/signed URL of the source image to upload . Either image_url or image_base64 is required.
- `mime_type` (string, optional): Optional content-type hint (e.g. image/png) used when the source does not declare one.
- `image_base64` (string, optional): Alternative to image_url: raw base64 image data (optionally a data: URI). Prefer image_url when available.

**Example Request:**

```bash
curl -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blog_id":"example_blog_id"}' \
  https://api.lots.blog/api/v1/lotsblog/blogs/:blog_id/images
```

---

## Support

For questions or issues, please visit https://api.lots.blog/docs or contact our support team.

## SDK and Libraries

We provide official SDKs for popular programming languages:

- **JavaScript/TypeScript**: Coming soon
- **Python**: Coming soon
- **Go**: Coming soon

## Changelog

Stay updated with the latest API changes:

- Visit https://api.lots.blog/docs for the latest documentation
- Check our changelog for API updates and deprecations

---

*Documentation generated on 2026-10-07T18:18:28.161Z*
