Skip to content

CMS API Reference ​

This guide explains how to use the CMS API to manage articles programmatically.

Authentication ​

All API endpoints (except health check and public settings) require authentication using an API key.

Generating an API Key ​

  1. Log in to your blog's admin panel
  2. Navigate to Settings > API Keys
  3. Click Generate New Key
  4. Copy the key immediately - it will only be shown once

Using the API Key ​

Include the API key in the Authorization header:

text
Authorization: Bearer YOUR_API_KEY

Base URL ​

EnvironmentBase URL
Productionhttps://cms-api.blog.tqer39.dev
Developmenthttps://cms-api.blog-dev.tqer39.dev
Localhttp://localhost:3101

Endpoints ​

Articles ​

List Articles ​

http
GET /v1/articles

Query Parameters:

ParameterTypeDescription
statusstringFilter by status: draft or published
tagstringFilter by tag name
categorystringFilter by category slug
pagenumberPage number (default: 1)
perPagenumberItems per page (default: 10)

Example:

bash
curl -X GET "https://cms-api.blog.tqer39.dev/v1/articles?status=published&page=1&perPage=10" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

json
{
  "articles": [
    {
      "id": "01H123456789ABCDEFGHIJ",
      "hash": "abc123def456",
      "title": "My Article",
      "description": "Article description",
      "content": "# Content here",
      "status": "published",
      "publishedAt": "2024-01-15T10:00:00Z",
      "createdAt": "2024-01-15T09:00:00Z",
      "updatedAt": "2024-01-15T10:00:00Z",
      "tags": ["tech", "typescript"],
      "categoryId": "cat_123",
      "category": { "id": "cat_123", "name": "Tech", "slug": "tech", "color": "#3b82f6" }
    }
  ],
  "total": 100,
  "page": 1,
  "perPage": 10
}

Get Article ​

http
GET /v1/articles/:hash

Example:

bash
curl -X GET "https://cms-api.blog.tqer39.dev/v1/articles/abc123def456" \
  -H "Authorization: Bearer YOUR_API_KEY"

Create Article ​

http
POST /v1/articles

Request Body:

typescript
interface ArticleInput {
  title: string;           // Required
  content: string;         // Required
  description?: string;
  status?: 'draft' | 'published';
  tags?: string[];
  categoryId?: string | null;
  headerImageId?: string | null;
  slideMode?: boolean;
  slideDuration?: number | null;
}

Example:

bash
curl -X POST "https://cms-api.blog.tqer39.dev/v1/articles" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "My New Article",
    "content": "# Hello World\n\nThis is my article content.",
    "description": "A brief description",
    "status": "draft",
    "tags": ["tech", "tutorial"]
  }'

Response (201 Created):

json
{
  "id": "01H123456789ABCDEFGHIJ",
  "hash": "abc123def456",
  "title": "My New Article",
  "content": "# Hello World\n\nThis is my article content.",
  "description": "A brief description",
  "status": "draft",
  "publishedAt": null,
  "createdAt": "2024-01-15T10:00:00Z",
  "updatedAt": "2024-01-15T10:00:00Z",
  "tags": ["tech", "tutorial"],
  "categoryId": null,
  "category": null
}

Update Article ​

http
PUT /v1/articles/:hash

Request Body: Partial ArticleInput - only include fields you want to update.

Example:

bash
curl -X PUT "https://cms-api.blog.tqer39.dev/v1/articles/abc123def456" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Updated Title",
    "tags": ["tech", "updated"]
  }'

Delete Article ​

http
DELETE /v1/articles/:hash

Example:

bash
curl -X DELETE "https://cms-api.blog.tqer39.dev/v1/articles/abc123def456" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

json
{
  "success": true
}

Publish Article ​

http
POST /v1/articles/:hash/publish

Sets the article status to published and records the publish timestamp.

Example:

bash
curl -X POST "https://cms-api.blog.tqer39.dev/v1/articles/abc123def456/publish" \
  -H "Authorization: Bearer YOUR_API_KEY"

Unpublish Article ​

http
POST /v1/articles/:hash/unpublish

Sets the article status back to draft.

Example:

bash
curl -X POST "https://cms-api.blog.tqer39.dev/v1/articles/abc123def456/unpublish" \
  -H "Authorization: Bearer YOUR_API_KEY"

API Key Management ​

Get API Key Status ​

http
GET /v1/api-key/status

Response:

json
{
  "hasKey": true,
  "enabled": true,
  "createdAt": "2024-01-15T10:00:00Z"
}

Generate New API Key ​

http
POST /v1/api-key/generate

WARNING

Generating a new key will invalidate the previous key.

Response:

json
{
  "key": "64-character-hex-string...",
  "createdAt": "2024-01-15T10:00:00Z"
}

Disable API Key ​

http
POST /v1/api-key/disable

Enable API Key ​

http
POST /v1/api-key/enable

Error Responses ​

All errors follow this format:

json
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable message",
    "details": {}
  }
}

Common Error Codes:

CodeHTTP StatusDescription
UNAUTHORIZED401Missing or invalid API key
NOT_FOUND404Resource not found
VALIDATION_ERROR400Invalid request body
INTERNAL_ERROR500Server error

Rate Limiting ​

The API implements rate limiting to prevent abuse. If you exceed the limit, you'll receive a 429 Too Many Requests response.

Example Workflows ​

Create and Publish an Article ​

bash
# 1. Create a draft article
RESPONSE=$(curl -s -X POST "https://cms-api.blog.tqer39.dev/v1/articles" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "My Article",
    "content": "# Hello\n\nContent here.",
    "status": "draft"
  }')

# 2. Extract the hash
HASH=$(echo $RESPONSE | jq -r '.hash')

# 3. Publish the article
curl -X POST "https://cms-api.blog.tqer39.dev/v1/articles/$HASH/publish" \
  -H "Authorization: Bearer YOUR_API_KEY"

Batch Update Tags ​

bash
# Update tags for an existing article
curl -X PUT "https://cms-api.blog.tqer39.dev/v1/articles/abc123def456" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tags": ["new-tag-1", "new-tag-2", "new-tag-3"]
  }'

Blog Documentation