| .. | ||
| create-site.md | ||
| create-tenant.md | ||
| create-user.md | ||
| delete-site.md | ||
| get-site.md | ||
| get-tenant-by-id.md | ||
| get-tenant-by-slug.md | ||
| get-user-by-id.md | ||
| get-user-profile.md | ||
| health-check.md | ||
| hello.md | ||
| list-sites.md | ||
| login.md | ||
| plugin-verify-api-key.md | ||
| README.md | ||
| refresh-token.md | ||
| register.md | ||
| rotate-site-api-key.md | ||
| verify-site.md | ||
MaplePress Backend API Documentation
This directory contains comprehensive API documentation for the MaplePress backend, organized by endpoint.
Base URL
http://localhost:8000
Quick Links
General
- Health Check -
GET /health
Authentication & User Management
- Register User & Tenant -
POST /api/v1/register - Login -
POST /api/v1/login - Refresh Token -
POST /api/v1/refresh - Hello (Authenticated) -
POST /api/v1/hello - Get User Profile -
GET /api/v1/me
Tenant Management
- Create Tenant -
POST /api/v1/tenants - Get Tenant by ID -
GET /api/v1/tenants/{id} - Get Tenant by Slug -
GET /api/v1/tenants/slug/{slug}
User Management
- Create User -
POST /api/v1/users - Get User by ID -
GET /api/v1/users/{id}
Site Management
- Create WordPress Site -
POST /api/v1/sites - List WordPress Sites -
GET /api/v1/sites - Get WordPress Site -
GET /api/v1/sites/{id} - Delete WordPress Site -
DELETE /api/v1/sites/{id} - Rotate Site API Key -
POST /api/v1/sites/{id}/rotate-api-key
WordPress Plugin API
- Verify API Key -
GET /api/v1/plugin/status
Authentication Overview
MaplePress uses a dual authentication system:
1. JWT Authentication (for Dashboard Users)
Used for user-facing dashboard endpoints (managing sites, users, tenants).
Format: Authorization: JWT {access_token}
Endpoints:
- All
/api/v1/sitesendpoints - All
/api/v1/usersendpoints - All
/api/v1/tenantsendpoints
How to get JWT:
- Register:
POST /api/v1/register - Login:
POST /api/v1/login - Use returned
access_tokenin Authorization header
2. API Key Authentication (for WordPress Plugins)
Used for WordPress plugin communication with the backend.
Format: Authorization: Bearer {api_key}
Endpoints:
- All
/api/v1/plugin/*endpoints (status, sync, search, etc.)
How to get API Key:
- Create a site via dashboard:
POST /api/v1/sites - Copy the
api_keyfrom response (shown only once!) - Configure WordPress plugin with the API key
API Key Format: live_sk_{40_random_characters} or test_sk_{40_random_characters}
Security:
- API keys are hashed using SHA-256 before storage
- Never logged or displayed after initial creation
- Can be rotated if compromised using the rotate-api-key endpoint
- API key middleware validates and populates site context in requests
- Only keys with
live_sk_ortest_sk_prefix are accepted
Test Mode vs Live Mode
MaplePress automatically generates different API key types based on your backend environment configuration.
Test Mode (test_sk_ keys)
Automatically enabled when:
APP_ENVIRONMENT=developmentin.env
Use for:
- Local development with
localhostURLs - Testing and experimentation
- CI/CD pipelines
Features:
- Test keys work identically to live keys
- Separate from production data
- Can be used for integration testing
- Generated automatically in development environment
Example:
# In your .env file:
APP_ENVIRONMENT=development
# Create a site (automatically gets test_sk_ key):
curl -X POST http://localhost:8000/api/v1/sites \
-H "Content-Type: application/json" \
-H "Authorization: JWT $TOKEN" \
-d '{
"domain": "localhost:8081",
"site_url": "http://localhost:8081"
}'
Response will include: "api_key": "test_sk_abc123..."
Live Mode (live_sk_ keys)
Automatically enabled when:
APP_ENVIRONMENT=productionin.env
Use for:
- Production WordPress sites
- Public-facing websites
- Real customer data
Features:
- Production-grade API keys
- Should be kept secure and never committed to version control
- Used for real traffic and billing
- Generated automatically in production environment
Example:
# In your .env file:
APP_ENVIRONMENT=production
# Create a site (automatically gets live_sk_ key):
curl -X POST http://localhost:8000/api/v1/sites \
-H "Content-Type: application/json" \
-H "Authorization: JWT $TOKEN" \
-d '{
"domain": "example.com",
"site_url": "https://example.com"
}'
Response will include: "api_key": "live_sk_xyz789..."
Environment Configuration
The API key type is automatically determined by the APP_ENVIRONMENT variable in .env:
# Development - Generates test_sk_ keys
APP_ENVIRONMENT=development
# Production - Generates live_sk_ keys
APP_ENVIRONMENT=production
Two simple options:
development= test keys (test_sk_*)production= live keys (live_sk_*)
No manual configuration needed! The backend automatically generates the appropriate key type based on your environment.
Testing Workflow
Here's a complete workflow to test the API from registration to creating sites:
1. Register a new user and tenant
# Save the response to extract tokens
# Note: timezone is optional and defaults to UTC if not provided
RESPONSE=$(curl -X POST http://localhost:8000/api/v1/register \
-H "Content-Type: application/json" \
-d '{
"email": "admin@mycompany.com",
"password": "SecurePass123!",
"first_name": "Admin",
"last_name": "User",
"name": "Admin User",
"tenant_name": "My Company",
"tenant_slug": "my-company",
"agree_terms_of_service": true,
"agree_promotions": false,
"agree_to_tracking_across_third_party_apps_and_services": false
}')
echo $RESPONSE | jq .
# Extract tokens (requires jq)
ACCESS_TOKEN=$(echo $RESPONSE | jq -r '.access_token')
TENANT_ID=$(echo $RESPONSE | jq -r '.tenant_id')
2. Login with existing credentials
# Login to get fresh tokens
LOGIN_RESPONSE=$(curl -X POST http://localhost:8000/api/v1/login \
-H "Content-Type: application/json" \
-d '{
"email": "admin@mycompany.com",
"password": "SecurePass123!",
"tenant_id": "'$TENANT_ID'"
}')
echo $LOGIN_RESPONSE | jq .
# Extract new access token
ACCESS_TOKEN=$(echo $LOGIN_RESPONSE | jq -r '.access_token')
3. Get tenant information
# By ID
curl -X GET http://localhost:8000/api/v1/tenants/$TENANT_ID \
-H "Authorization: JWT $ACCESS_TOKEN" | jq .
# By slug
curl -X GET http://localhost:8000/api/v1/tenants/slug/my-company \
-H "Authorization: JWT $ACCESS_TOKEN" | jq .
4. Create a new WordPress site
SITE_RESPONSE=$(curl -X POST http://localhost:8000/api/v1/sites \
-H "Content-Type: application/json" \
-H "Authorization: JWT $ACCESS_TOKEN" \
-d '{
"domain": "example.com",
"site_url": "https://example.com"
}')
echo $SITE_RESPONSE | jq .
# Extract site ID and API key
SITE_ID=$(echo $SITE_RESPONSE | jq -r '.id')
API_KEY=$(echo $SITE_RESPONSE | jq -r '.api_key')
5. Verify API key (as WordPress plugin)
curl -X GET http://localhost:8000/api/v1/plugin/status \
-H "Authorization: Bearer $API_KEY" | jq .
Multi-Tenancy
This API implements multi-tenancy where:
- Each tenant is isolated from other tenants
- Users belong to specific tenants
- The
X-Tenant-IDheader is required for tenant-scoped operations (in development mode) - In production, the tenant context will be extracted from the JWT token
Error Handling
MaplePress uses RFC 9457 (Problem Details for HTTP APIs) for standardized, machine-readable error responses.
Standard: RFC 9457 - Problem Details for HTTP APIs
Content-Type: application/problem+json
Error Response Format
All error responses follow the RFC 9457 format:
{
"type": "about:blank",
"title": "Error Type",
"status": 400,
"detail": "Human-readable explanation of the error"
}
Validation Errors (400 Bad Request)
For validation errors, an additional errors field provides field-level details:
{
"type": "about:blank",
"title": "Validation Error",
"status": 400,
"detail": "One or more validation errors occurred",
"errors": {
"email": ["Invalid email format", "Email is required"],
"password": ["Password must be at least 8 characters"]
}
}
Common HTTP Status Codes
200 OK: Successful GET request201 Created: Successful resource creation400 Bad Request: Invalid input or missing required fields (with validation errors)401 Unauthorized: Authentication required or invalid token403 Forbidden: Authenticated but not authorized404 Not Found: Resource not found409 Conflict: Resource already exists (duplicate)429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server-side error
Example Error Responses
401 Unauthorized:
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Authentication required"
}
409 Conflict:
{
"type": "about:blank",
"title": "Conflict",
"status": 409,
"detail": "Email already exists"
}
500 Internal Server Error:
{
"type": "about:blank",
"title": "Internal Server Error",
"status": 500,
"detail": "Failed to process request"
}
Development vs Production
Development Mode (current):
- Tenant context via
X-Tenant-IDheader - Less strict validation
- Debug logging enabled
- Test API keys (
test_sk_*) generated
Production Mode:
- Tenant context extracted from JWT token claims
- Strict validation
- Info/Error logging only
- Live API keys (
live_sk_*) generated