# 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](health-check.md) - `GET /health` ### Authentication & User Management - [Register User & Tenant](register.md) - `POST /api/v1/register` - [Login](login.md) - `POST /api/v1/login` - [Refresh Token](refresh-token.md) - `POST /api/v1/refresh` - [Hello (Authenticated)](hello.md) - `POST /api/v1/hello` - [Get User Profile](get-user-profile.md) - `GET /api/v1/me` ### Tenant Management - [Create Tenant](create-tenant.md) - `POST /api/v1/tenants` - [Get Tenant by ID](get-tenant-by-id.md) - `GET /api/v1/tenants/{id}` - [Get Tenant by Slug](get-tenant-by-slug.md) - `GET /api/v1/tenants/slug/{slug}` ### User Management - [Create User](create-user.md) - `POST /api/v1/users` - [Get User by ID](get-user-by-id.md) - `GET /api/v1/users/{id}` ### Site Management - [Create WordPress Site](create-site.md) - `POST /api/v1/sites` - [List WordPress Sites](list-sites.md) - `GET /api/v1/sites` - [Get WordPress Site](get-site.md) - `GET /api/v1/sites/{id}` - [Delete WordPress Site](delete-site.md) - `DELETE /api/v1/sites/{id}` - [Rotate Site API Key](rotate-site-api-key.md) - `POST /api/v1/sites/{id}/rotate-api-key` ### WordPress Plugin API - [Verify API Key](plugin-verify-api-key.md) - `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/sites` endpoints - All `/api/v1/users` endpoints - All `/api/v1/tenants` endpoints **How to get JWT**: 1. Register: `POST /api/v1/register` 2. Login: `POST /api/v1/login` 3. Use returned `access_token` in 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**: 1. Create a site via dashboard: `POST /api/v1/sites` 2. Copy the `api_key` from response (shown only once!) 3. 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_` or `test_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=development` in `.env` **Use for:** - Local development with `localhost` URLs - 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:** ```bash # 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=production` in `.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:** ```bash # 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`: ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash 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) ```bash 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-ID` header 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](https://datatracker.ietf.org/doc/html/rfc9457) **Content-Type**: `application/problem+json` ### Error Response Format All error responses follow the RFC 9457 format: ```json { "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: ```json { "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 request - `201 Created`: Successful resource creation - `400 Bad Request`: Invalid input or missing required fields (with validation errors) - `401 Unauthorized`: Authentication required or invalid token - `403 Forbidden`: Authenticated but not authorized - `404 Not Found`: Resource not found - `409 Conflict`: Resource already exists (duplicate) - `429 Too Many Requests`: Rate limit exceeded - `500 Internal Server Error`: Server-side error ### Example Error Responses **401 Unauthorized:** ```json { "type": "about:blank", "title": "Unauthorized", "status": 401, "detail": "Authentication required" } ``` **409 Conflict:** ```json { "type": "about:blank", "title": "Conflict", "status": 409, "detail": "Email already exists" } ``` **500 Internal Server Error:** ```json { "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-ID` header - 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