Files
alexandrev-tibco 4f5ab09b66 +1
2026-02-02 17:43:53 +01:00

10 KiB

API Documentation

The SEO Optimizer provides a REST API for manual optimization triggers and managing drafts.

Base URL

http://localhost:8080/api/v1

Multi-Site Header

When running multiple sites, include the X-WPSK-Site header with the site ID to scope requests:

X-WPSK-Site: padre

Endpoints

1. Health Check

Check if the API server is running.

GET /health

Response:

{
  "status": "ok",
  "version": "1.0.0"
}

2. Optimize Post

Manually trigger optimization for a specific post.

POST /optimize
Content-Type: application/json

{
  "post_id": 123,
  "language": "es"
}

Parameters:

  • post_id (int, required): WordPress post ID to optimize
  • language (string, optional): Language code (defaults to "en")

Response:

{
  "job_id": "uuid-string",
  "status": "accepted"
}

Example:

curl -X POST http://localhost:8080/api/v1/optimize \
  -H "Content-Type: application/json" \
  -d '{"post_id": 123, "language": "es"}'

3. Check Job Status

Check the status of an optimization job.

GET /status/{job_id}

Response:

{
  "id": "uuid-string",
  "post_id": 123,
  "language": "es",
  "status": "completed",
  "started_at": "2025-01-24T10:00:00Z",
  "ended_at": "2025-01-24T10:02:30Z",
  "summary": "Optimization completed successfully"
}

Example:

curl http://localhost:8080/api/v1/status/abc-123-def

4. List Pending Drafts

Get all pending draft posts that are waiting for review.

GET /pending

Response:

{
  "count": 5,
  "records": [
    {
      "post_id": 123,
      "original_post_id": 123,
      "draft_post_id": 456,
      "post_title": "How to Test Helm Charts in Production",
      "language": "en",
      "optimized_at": "2025-01-24T10:00:00Z",
      "status": "pending",
      "optimization": {
        "seo_meta": {
          "title": "Ultimate Guide: Testing Helm Charts in Production 2025",
          "description": "Learn production-grade Helm chart testing with kubeconform, chart-testing, and security scanning. Prevent outages with this complete guide."
        },
        "content_optimization": {
          "changes": [...],
          "internal_links": [...]
        },
        "faq_block": {
          "should_create": true,
          "questions": [...]
        }
      }
    }
  ]
}

Example:

curl http://localhost:8080/api/v1/pending

5. Get Optimization Details

Get detailed optimization information for a specific post.

GET /optimization/{post_id}

Parameters:

  • post_id (int): Original WordPress post ID

Response:

{
  "post_id": 123,
  "original_post_id": 123,
  "draft_post_id": 456,
  "post_title": "How to Test Helm Charts in Production",
  "language": "en",
  "optimized_at": "2025-01-24T10:00:00Z",
  "status": "pending",
  "optimization": {
    "seo_meta": {...},
    "content_optimization": {...},
    "faq_block": {...},
    "validation": {...},
    "summary": "Enhanced SEO with 8 keyword injections..."
  }
}

Example:

curl http://localhost:8080/api/v1/optimization/123

6. Apply Draft

Apply a pending draft to the original published post and delete the draft.

POST /apply-draft
Content-Type: application/json

{
  "draft_post_id": 456
}

Parameters:

  • draft_post_id (int, required): WordPress draft post ID to apply

Response:

{
  "status": "applied",
  "message": "Draft applied to original post and draft deleted"
}

Example:

curl -X POST http://localhost:8080/api/v1/apply-draft \
  -H "Content-Type: application/json" \
  -d '{"draft_post_id": 456}'

Or use the helper script:

./scripts/apply-draft.sh 456

7. Get Draft Content

Fetch draft content for CLI-friendly review.

GET /drafts/{draft_post_id}

Response:

{
  "id": 456,
  "status": "draft",
  "title": "Draft title",
  "excerpt": "Draft excerpt",
  "content": "<p>Rendered HTML...</p>"
}

8. Ideas: List

List stored idea records by status.

GET /ideas?status=new

Response:

{
  "count": 3,
  "ideas": [
    {
      "id": "uuid",
      "seo_title": "Kubernetes Pod Security Standards: What Changed in 2025",
      "summary": "Idea summary...",
      "status": "new",
      "created_at": "2026-01-25T09:00:00Z"
    }
  ]
}

9. Ideas: Generate Now

Trigger idea generation from Reddit immediately.

POST /ideas/generate

10. Ideas: Generate Drafts

Generate full English + Spanish drafts for an idea.

POST /ideas/{id}/draft

11. Ideas: Publish Drafts

Publish the drafts created for an idea.

POST /ideas/{id}/publish

12. Ideas: Delete

Delete an idea record (and any drafts created from it).

POST /ideas/{id}/delete

13. Outreach: List

List outreach suggestions.

GET /outreach?status=new

14. Outreach: Generate Now

Generate outreach suggestions from Reddit now.

POST /outreach/generate

15. Outreach: Delete

Delete an outreach suggestion.

POST /outreach/{id}/delete

16. Newsletter: List

List newsletter drafts.

GET /newsletter?status=draft

17. Newsletter: Generate Now

Generate a newsletter draft from RSS + Reddit.

POST /newsletter/generate

18. Newsletter: Delete

Delete a newsletter draft.

POST /newsletter/{id}/delete

Fetch the latest broken link report (only posts with broken links are returned).

GET /broken-links

Trigger a broken link scan in the background.

POST /broken-links/scan

21. Image Audit: Latest Report

Fetch the latest image audit report (only posts with external images are returned).

GET /image-audit

22. Image Audit: Scan Now

Trigger an image audit in the background.

POST /image-audit/scan

23. Image Audit: Fix External Images

Create a draft that replaces external images with locally hosted AVIF uploads.

POST /image-audit/fix {"post_id": 123}

Sync the English featured image to the Spanish translation.

POST /image-audit/sync-featured {"post_id": 123, "target_lang": "es"}

25. Orphan Posts: List

List posts missing a Spanish translation.

GET /orphans?source=en&target=es

26. Translate Post: Generate Draft

Generate a Spanish draft linked via Polylang.

POST /translate {"post_id": 123, "target_lang": "es"}

Workflow

Typical Optimization Workflow

  1. Trigger Optimization (automatic via scheduler or manual via API)

    POST /optimize {"post_id": 123, "language": "en"}
    
    • Creates a draft copy with optimized content
    • Original post stays published
    • Optimization record saved to storage
  2. Review Pending Drafts

    GET /pending
    
    • Lists all draft posts waiting for review
    • Shows what changes were made
  3. Check Optimization Details (optional)

    GET /optimization/123
    
    • See detailed changes, FAQ blocks, internal links, etc.
  4. Review in WordPress Admin

    • Go to Posts → Drafts
    • Find the draft post (linked to original via meta)
    • Review changes in WordPress editor
  5. Apply Draft (when satisfied)

    POST /apply-draft {"draft_post_id": 456}
    
    • Copies draft content to original post
    • Keeps original post published
    • Deletes the draft
    • Updates storage status to "applied"

Error Responses

All endpoints return appropriate HTTP status codes:

  • 200 OK: Success
  • 202 Accepted: Request accepted (async processing)
  • 400 Bad Request: Invalid input
  • 404 Not Found: Resource not found
  • 500 Internal Server Error: Server error

Error response format:

HTTP/1.1 400 Bad Request
post_id must be positive

File Storage

Optimization records are stored in the file system at the configured storage.base_path:

./data/optimizations/
├── pending/       # Drafts waiting for review
│   ├── 123_1737715200.json
│   └── 456_1737718800.json
├── applied/       # Successfully applied optimizations
│   └── 789_1737629200.json
└── rejected/      # Manually rejected drafts

Each file contains the complete optimization record including:

  • Post metadata
  • Optimization details
  • SEO meta
  • Content changes
  • FAQ blocks
  • Internal links
  • Validation results

Broken link reports are stored at the configured link_checker.base_path:

./data/broken-links/
├── 1737730000_1737730000.json
└── 1737816400_1737816400.json

Image audit reports are stored at the configured image_audit.base_path:

./data/image-audits/
├── 1737730000_1737730000.json
└── 1737816400_1737816400.json

Audit Log

List recent actions recorded by the system (CLI/WebUI/API).

GET /audit?limit=100

Response:

{
  "count": 2,
  "records": [
    {
      "id": "uuid-string",
      "created_at": "2025-01-24T10:05:00Z",
      "actor": "cli",
      "action": "draft_applied",
      "summary": "Applied draft 456 to original post 123",
      "post_id": 123,
      "draft_post_id": 456
    }
  ]
}

Audit records are stored at the configured audit.base_path.


Configuration

Enable/disable the API server in config.yaml:

api:
  enabled: true
  port: 8080

storage:
  base_path: "./data/optimizations"

audit:
  base_path: "./data/audit"

link_checker:
  base_path: "./data/broken-links"

image_audit:
  base_path: "./data/image-audits"

Security

IMPORTANT: The API has no authentication and is intended for local access only.

  • Do not expose the API to the internet
  • Use a reverse proxy with authentication if needed
  • Run on localhost or behind a firewall

Monitoring

Check server logs for detailed operation information:

# View logs in JSON format
tail -f logs/optimizer.log | jq

# Filter for API-related logs
tail -f logs/optimizer.log | jq 'select(.component == "api")'