API Documentation

Autofocus provides REST API endpoints for content delivery, integration, and automation. Access user profiles, pages, and blocks programmatically for custom applications and external integrations.

🌐 API Overview

Base URL

https://autofoc.us/api

All API endpoints are accessed via this base URL with RESTful patterns.

Response Format

Content-Type: application/json

All responses are returned in JSON format with consistent error handling.

📦 Content Delivery API

Get User Profile

GET /api/user/[username]

Retrieve public profile information for a user.

Example Request

curl https://autofoc.us/api/user/nate
  -H "Accept: application/json"

Example Response

{
  "id": "uuid",
  "username": "nate",
  "display_name": "Nate",
  "bio": "Creator bio text",
  "avatar_url": "https://...",
  "social_links": {...},
  "created_at": "2024-01-01T00:00:00Z"
}

Get Page Content

GET /[username]/[page]?api=1

Retrieve all blocks for a specific page in JSON format.

Example Request

curl https://autofoc.us/nate/portfolio?api=1
  -H "Accept: application/json"

Example Response

[
  {
    "id": "uuid",
    "type": "markdown",
    "content": {
      "text": "# Welcome to my page"
    },
    "order_index": 0,
    "created_at": "2024-01-01T00:00:00Z"
  },
  {
    "id": "uuid", 
    "type": "image",
    "content": {
      "url": "https://...",
      "alt": "Photo description"
    },
    "order_index": 1
  }
]

🔐 Authentication & Verification

Verify Redirect Password

POST /api/verify-redirect-password

Verify password for protected redirect pages.

Request Body

{
  "username": "nate",
  "pageSlug": "private-page",
  "password": "secret123"
}

Response

{
  "success": true
}

// Or on failure:
{
  "success": false,
  "error": "Invalid password"
}

🧩 Block Types API Reference

Each block type has a consistent structure but different content schemas. Here are the main block types and their API formats:

Text/Markdown Block

{
  "type": "markdown",
  "content": {
    "text": "# Heading\n\nParagraph text"
  }
}

Image Block

{
  "type": "image",
  "content": {
    "url": "https://example.com/image.jpg",
    "alt": "Image description",
    "caption": "Optional caption"
  }
}

Link Block

{
  "type": "link",
  "content": {
    "url": "https://example.com",
    "title": "Link Title",
    "description": "Description text"
  }
}

Checklist Block

{
  "type": "checklist",
  "content": {
    "items": [
      {"text": "Task 1", "completed": false},
      {"text": "Task 2", "completed": true}
    ]
  }
}

Code Block

{
  "type": "code",
  "content": {
    "code": "console.log('Hello');",
    "language": "javascript",
    "theme": "dark"
  }
}

Audio Block

{
  "type": "audio",
  "content": {
    "url": "https://example.com/audio.mp3",
    "title": "Audio Title",
    "duration": 180
  }
}

Location Block

{
  "type": "location",
  "content": {
    "latitude": 40.7128,
    "longitude": -74.0060,
    "title": "Location Name",
    "description": "Details"
  }
}

Kanban Block

{
  "type": "kanban",
  "content": {
    "columns": [
      {
        "title": "To Do",
        "cards": [
          {"title": "Task", "description": "Details"}
        ]
      }
    ]
  }
}

⚠️ Error Handling & Status Codes

HTTP Status Codes

200Success
400Bad Request
404Not Found
500Server Error

Error Response Format

{
  "error": "Profile not found",
  "code": "PROFILE_NOT_FOUND",
  "message": "The requested user profile does not exist.",
  "timestamp": "2024-01-01T00:00:00Z"
}

🚦 Rate Limiting & Best Practices

Rate Limits

• Public API: 100 requests per minute
• Authenticated API: 1000 requests per minute
• Bulk operations: 10 requests per minute
• Rate limit headers included in responses

Best Practices

• Cache responses when possible
• Use pagination for large datasets
• Implement exponential backoff for retries
• Monitor rate limit headers
• Use webhook subscriptions for real-time updates

🔌 Integration Examples

JavaScript/Node.js

// Fetch user profile
const response = await fetch('https://autofoc.us/api/user/nate');
const profile = await response.json();

// Get page blocks
const pageResponse = await fetch('https://autofoc.us/nate/portfolio?api=1');
const blocks = await pageResponse.json();

// Filter for specific block types
const imageBlocks = blocks.filter(block => block.type === 'image');
const textBlocks = blocks.filter(block => block.type === 'markdown');

Python

import requests

# Get user profile
response = requests.get('https://autofoc.us/api/user/nate')
profile = response.json()

# Get page content
page_response = requests.get('https://autofoc.us/nate/portfolio?api=1')
blocks = page_response.json()

# Process blocks by type
for block in blocks:
    if block['type'] == 'image':
        print(f"Image: {block['content']['url']}")
    elif block['type'] == 'markdown':
        print(f"Text: {block['content']['text'][:100]}...")