Initial commit: Open sourcing all of the Maple Open Technologies code.
This commit is contained in:
commit
755d54a99d
2010 changed files with 448675 additions and 0 deletions
373
cloud/maplepress-backend/docs/API/README.md
Normal file
373
cloud/maplepress-backend/docs/API/README.md
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
# 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
|
||||
110
cloud/maplepress-backend/docs/API/create-site.md
Normal file
110
cloud/maplepress-backend/docs/API/create-site.md
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
# Create WordPress Site
|
||||
|
||||
**POST /api/v1/sites**
|
||||
|
||||
Create a new WordPress site and generate API credentials for the WordPress plugin.
|
||||
|
||||
**Authentication**: Required (JWT Bearer token)
|
||||
|
||||
**Headers**:
|
||||
- `Content-Type: application/json`
|
||||
- `Authorization: JWT {access_token}` (tenant is automatically determined from JWT)
|
||||
|
||||
**Request Body**:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| domain | string | Yes | WordPress site domain (e.g., example.com) |
|
||||
| site_url | string | Yes | Full WordPress site URL (e.g., https://example.com) |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/sites \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
|
||||
-d '{
|
||||
"domain": "example.com",
|
||||
"site_url": "https://example.com"
|
||||
}'
|
||||
```
|
||||
|
||||
**Example Response** (201 Created):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||
"domain": "example.com",
|
||||
"site_url": "https://example.com",
|
||||
"api_key": "live_sk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0",
|
||||
"verification_token": "mvp_xyz789abc123",
|
||||
"status": "pending",
|
||||
"search_index_name": "site_a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
||||
}
|
||||
```
|
||||
|
||||
**Important Notes**:
|
||||
- The `api_key` is shown **only once** - save it immediately!
|
||||
- The site starts with `status: "pending"` until verified
|
||||
- The `verification_token` should be used by the WordPress plugin for site verification
|
||||
- The `search_index_name` is the Meilisearch index for this site
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Validation Error Response** (400 Bad Request):
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Validation Error",
|
||||
"status": 400,
|
||||
"detail": "One or more validation errors occurred",
|
||||
"errors": {
|
||||
"domain": ["Invalid domain format", "Domain is required"],
|
||||
"site_url": ["Invalid URL format", "Site URL is required"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**Common Validation Error Messages**:
|
||||
|
||||
| Field | Error Messages |
|
||||
|-------|----------------|
|
||||
| domain | "Invalid domain format", "Domain is required" |
|
||||
| site_url | "Invalid URL format", "Site URL is required" |
|
||||
|
||||
**Other Error Responses**:
|
||||
|
||||
- `401 Unauthorized`: Missing or invalid JWT token
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
- `409 Conflict`: Domain already registered by another user
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Conflict",
|
||||
"status": 409,
|
||||
"detail": "Domain already exists"
|
||||
}
|
||||
```
|
||||
|
||||
- `500 Internal Server Error`: Server error
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to create site"
|
||||
}
|
||||
```
|
||||
88
cloud/maplepress-backend/docs/API/create-tenant.md
Normal file
88
cloud/maplepress-backend/docs/API/create-tenant.md
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# Create Tenant
|
||||
|
||||
**POST /api/v1/tenants**
|
||||
|
||||
Create a new tenant (organization).
|
||||
|
||||
**Authentication**: Required (JWT Bearer token)
|
||||
|
||||
**Headers**:
|
||||
- `Content-Type: application/json`
|
||||
- `Authorization: JWT {access_token}`
|
||||
|
||||
**Request Body**:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| name | string | Yes | Tenant/organization name |
|
||||
| slug | string | Yes | URL-friendly tenant identifier |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/tenants \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
|
||||
-d '{
|
||||
"name": "TechStart Inc",
|
||||
"slug": "techstart"
|
||||
}'
|
||||
```
|
||||
|
||||
**Example Response** (201 Created):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "850e8400-e29b-41d4-a716-446655440000",
|
||||
"name": "TechStart Inc",
|
||||
"slug": "techstart",
|
||||
"status": "active",
|
||||
"created_at": "2024-10-24T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**400 Bad Request** - Invalid input:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Bad Request",
|
||||
"status": 400,
|
||||
"detail": "Invalid request body format"
|
||||
}
|
||||
```
|
||||
|
||||
**401 Unauthorized** - Missing or invalid JWT token:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
**409 Conflict** - Tenant slug already exists:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Conflict",
|
||||
"status": 409,
|
||||
"detail": "Tenant slug already exists"
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to create tenant"
|
||||
}
|
||||
```
|
||||
91
cloud/maplepress-backend/docs/API/create-user.md
Normal file
91
cloud/maplepress-backend/docs/API/create-user.md
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# Create User
|
||||
|
||||
**POST /api/v1/users**
|
||||
|
||||
Create a new user within a tenant.
|
||||
|
||||
**Authentication**: Required (JWT Bearer token)
|
||||
|
||||
**Tenant Context**: Required
|
||||
|
||||
**Headers**:
|
||||
- `Content-Type: application/json`
|
||||
- `Authorization: JWT {access_token}`
|
||||
- `X-Tenant-ID: {tenant_id}` (required in development mode)
|
||||
|
||||
**Request Body**:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| email | string | Yes | User's email address |
|
||||
| name | string | Yes | User's full name |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/users \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
|
||||
-H "X-Tenant-ID: 850e8400-e29b-41d4-a716-446655440000" \
|
||||
-d '{
|
||||
"email": "jane@techstart.com",
|
||||
"name": "Jane Smith"
|
||||
}'
|
||||
```
|
||||
|
||||
**Example Response** (201 Created):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "950e8400-e29b-41d4-a716-446655440000",
|
||||
"email": "jane@techstart.com",
|
||||
"name": "Jane Smith",
|
||||
"created_at": "2024-10-24T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**400 Bad Request** - Invalid input:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Bad Request",
|
||||
"status": 400,
|
||||
"detail": "Invalid request body format"
|
||||
}
|
||||
```
|
||||
|
||||
**401 Unauthorized**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
**409 Conflict** - Email already exists:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Conflict",
|
||||
"status": 409,
|
||||
"detail": "User email already exists in this tenant"
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to create user"
|
||||
}
|
||||
```
|
||||
74
cloud/maplepress-backend/docs/API/delete-site.md
Normal file
74
cloud/maplepress-backend/docs/API/delete-site.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# Delete WordPress Site
|
||||
|
||||
**DELETE /api/v1/sites/{id}**
|
||||
|
||||
Delete a WordPress site and all associated data.
|
||||
|
||||
**Authentication**: Required (JWT Bearer token)
|
||||
|
||||
**Headers**:
|
||||
- `Authorization: JWT {access_token}`
|
||||
|
||||
**URL Parameters**:
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| id | UUID | Yes | Site ID |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X DELETE http://localhost:8000/api/v1/sites/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Site deleted successfully"
|
||||
}
|
||||
```
|
||||
|
||||
**Important Notes**:
|
||||
- This is a **hard delete** - removes the site from all Cassandra tables
|
||||
- The site's API key will immediately stop working
|
||||
- The Meilisearch index should also be deleted (implement separately)
|
||||
- This action cannot be undone
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**401 Unauthorized**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
**404 Not Found**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Not Found",
|
||||
"status": 404,
|
||||
"detail": "Site not found or doesn't belong to your tenant"
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to delete site"
|
||||
}
|
||||
```
|
||||
90
cloud/maplepress-backend/docs/API/get-site.md
Normal file
90
cloud/maplepress-backend/docs/API/get-site.md
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
# Get WordPress Site
|
||||
|
||||
**GET /api/v1/sites/{id}**
|
||||
|
||||
Retrieve detailed information about a specific WordPress site.
|
||||
|
||||
**Authentication**: Required (JWT Bearer token)
|
||||
|
||||
**Headers**:
|
||||
- `Authorization: JWT {access_token}`
|
||||
|
||||
**URL Parameters**:
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| id | UUID | Yes | Site ID |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:8000/api/v1/sites/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||
"tenant_id": "t1t2t3t4-t5t6-7890-tttt-tttttttttttt",
|
||||
"domain": "example.com",
|
||||
"site_url": "https://example.com",
|
||||
"api_key_prefix": "live_sk_a1b2",
|
||||
"api_key_last_four": "s9t0",
|
||||
"status": "active",
|
||||
"is_verified": true,
|
||||
"search_index_name": "site_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||
"total_pages_indexed": 145,
|
||||
"last_indexed_at": "2024-10-27T14:30:00Z",
|
||||
"plugin_version": "1.0.0",
|
||||
"storage_used_bytes": 52428800,
|
||||
"search_requests_count": 234,
|
||||
"monthly_pages_indexed": 50,
|
||||
"last_reset_at": "2024-10-01T00:00:00Z",
|
||||
"created_at": "2024-10-27T10:00:00Z",
|
||||
"updated_at": "2024-10-27T14:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Notes**:
|
||||
- Returns full site details including usage tracking statistics
|
||||
- API key is never returned (only prefix and last 4 chars for identification)
|
||||
- Useful for dashboard display and usage monitoring
|
||||
- Usage-based billing: No quotas or limits, only usage tracking
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**401 Unauthorized**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
**404 Not Found**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Not Found",
|
||||
"status": 404,
|
||||
"detail": "Site not found or doesn't belong to your tenant"
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to retrieve site"
|
||||
}
|
||||
```
|
||||
72
cloud/maplepress-backend/docs/API/get-tenant-by-id.md
Normal file
72
cloud/maplepress-backend/docs/API/get-tenant-by-id.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# Get Tenant by ID
|
||||
|
||||
**GET /api/v1/tenants/{id}**
|
||||
|
||||
Retrieve tenant information by tenant ID.
|
||||
|
||||
**Authentication**: Required (JWT Bearer token)
|
||||
|
||||
**Headers**:
|
||||
- `Authorization: JWT {access_token}`
|
||||
|
||||
**URL Parameters**:
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| id | UUID | Yes | Tenant ID |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:8000/api/v1/tenants/850e8400-e29b-41d4-a716-446655440000 \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "850e8400-e29b-41d4-a716-446655440000",
|
||||
"name": "TechStart Inc",
|
||||
"slug": "techstart",
|
||||
"status": "active",
|
||||
"created_at": "2024-10-24T00:00:00Z",
|
||||
"updated_at": "2024-10-24T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**401 Unauthorized**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
**404 Not Found**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Not Found",
|
||||
"status": 404,
|
||||
"detail": "Tenant not found"
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to retrieve tenant"
|
||||
}
|
||||
```
|
||||
72
cloud/maplepress-backend/docs/API/get-tenant-by-slug.md
Normal file
72
cloud/maplepress-backend/docs/API/get-tenant-by-slug.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# Get Tenant by Slug
|
||||
|
||||
**GET /api/v1/tenants/slug/{slug}**
|
||||
|
||||
Retrieve tenant information by tenant slug.
|
||||
|
||||
**Authentication**: Required (JWT Bearer token)
|
||||
|
||||
**Headers**:
|
||||
- `Authorization: JWT {access_token}`
|
||||
|
||||
**URL Parameters**:
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| slug | string | Yes | Tenant slug |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:8000/api/v1/tenants/slug/techstart \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "850e8400-e29b-41d4-a716-446655440000",
|
||||
"name": "TechStart Inc",
|
||||
"slug": "techstart",
|
||||
"status": "active",
|
||||
"created_at": "2024-10-24T00:00:00Z",
|
||||
"updated_at": "2024-10-24T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**401 Unauthorized**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
**404 Not Found**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Not Found",
|
||||
"status": 404,
|
||||
"detail": "Tenant not found"
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to retrieve tenant"
|
||||
}
|
||||
```
|
||||
85
cloud/maplepress-backend/docs/API/get-user-by-id.md
Normal file
85
cloud/maplepress-backend/docs/API/get-user-by-id.md
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# Get User by ID
|
||||
|
||||
**GET /api/v1/users/{id}**
|
||||
|
||||
Retrieve user information by user ID within a tenant context.
|
||||
|
||||
**Authentication**: Required (JWT Bearer token)
|
||||
|
||||
**Tenant Context**: Required
|
||||
|
||||
**Headers**:
|
||||
- `Authorization: JWT {access_token}`
|
||||
- `X-Tenant-ID: {tenant_id}` (required in development mode)
|
||||
|
||||
**URL Parameters**:
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| id | UUID | Yes | User ID |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:8000/api/v1/users/950e8400-e29b-41d4-a716-446655440000 \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
|
||||
-H "X-Tenant-ID: 850e8400-e29b-41d4-a716-446655440000"
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "950e8400-e29b-41d4-a716-446655440000",
|
||||
"email": "jane@techstart.com",
|
||||
"name": "Jane Smith",
|
||||
"created_at": "2024-10-24T00:00:00Z",
|
||||
"updated_at": "2024-10-24T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**400 Bad Request** - Missing tenant context:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Bad Request",
|
||||
"status": 400,
|
||||
"detail": "Tenant context required"
|
||||
}
|
||||
```
|
||||
|
||||
**401 Unauthorized**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
**404 Not Found**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Not Found",
|
||||
"status": 404,
|
||||
"detail": "User not found in this tenant"
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to retrieve user"
|
||||
}
|
||||
```
|
||||
51
cloud/maplepress-backend/docs/API/get-user-profile.md
Normal file
51
cloud/maplepress-backend/docs/API/get-user-profile.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Get User Profile
|
||||
|
||||
**GET /api/v1/me**
|
||||
|
||||
Get the authenticated user's profile information from the JWT token.
|
||||
|
||||
**Authentication**: Required (JWT token)
|
||||
|
||||
**Headers**:
|
||||
- `Authorization: JWT {access_token}`
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:8000/api/v1/me \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"email": "john@example.com",
|
||||
"name": "John Doe",
|
||||
"role": "owner",
|
||||
"tenant_id": "650e8400-e29b-41d4-a716-446655440000"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**401 Unauthorized** - Missing or invalid JWT token:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
**Notes**:
|
||||
- Returns user information extracted from the JWT token claims
|
||||
- No database query required - all data comes from the token
|
||||
- Useful for displaying user information in the dashboard
|
||||
- Can be used to verify the current authenticated user's identity
|
||||
23
cloud/maplepress-backend/docs/API/health-check.md
Normal file
23
cloud/maplepress-backend/docs/API/health-check.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Health Check
|
||||
|
||||
## GET /health
|
||||
|
||||
Check if the service is running and healthy.
|
||||
|
||||
**Authentication**: None required
|
||||
|
||||
**Headers**: None required
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:8000/health
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "healthy"
|
||||
}
|
||||
```
|
||||
66
cloud/maplepress-backend/docs/API/hello.md
Normal file
66
cloud/maplepress-backend/docs/API/hello.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# Hello (Authenticated)
|
||||
|
||||
**POST /api/v1/hello**
|
||||
|
||||
A simple authenticated endpoint that returns a personalized greeting message. This endpoint demonstrates JWT authentication and can be used to verify that your access token is working correctly.
|
||||
|
||||
**Authentication**: Required (JWT token)
|
||||
|
||||
**Headers**:
|
||||
- `Content-Type: application/json`
|
||||
- `Authorization: JWT {access_token}`
|
||||
|
||||
**Request Body**:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| name | string | Yes | Name to include in greeting |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/hello \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
|
||||
-d '{"name": "Alice"}'
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Hello, Alice! Welcome to MaplePress Backend."
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**400 Bad Request** - Missing name field:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Bad Request",
|
||||
"status": 400,
|
||||
"detail": "Name is required"
|
||||
}
|
||||
```
|
||||
|
||||
**401 Unauthorized** - Missing or invalid JWT token:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
**Notes**:
|
||||
- This endpoint requires a valid JWT access token
|
||||
- The name field is required in the request body
|
||||
- Useful for testing authentication and verifying token validity
|
||||
- Returns a personalized greeting with the provided name
|
||||
79
cloud/maplepress-backend/docs/API/list-sites.md
Normal file
79
cloud/maplepress-backend/docs/API/list-sites.md
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# List WordPress Sites
|
||||
|
||||
**GET /api/v1/sites**
|
||||
|
||||
Retrieve all WordPress sites for the authenticated user's tenant.
|
||||
|
||||
**Authentication**: Required (JWT Bearer token)
|
||||
|
||||
**Headers**:
|
||||
- `Authorization: JWT {access_token}`
|
||||
|
||||
**Query Parameters**:
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| page_size | integer | No | Number of results per page (default: 20, max: 100) |
|
||||
| page_state | string | No | Pagination token from previous response |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X GET 'http://localhost:8000/api/v1/sites?page_size=20' \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"sites": [
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||
"domain": "example.com",
|
||||
"status": "active",
|
||||
"is_verified": true,
|
||||
"created_at": "2024-10-27T10:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": "b2c3d4e5-f6g7-8901-bcde-f12345678901",
|
||||
"domain": "another-site.com",
|
||||
"status": "pending",
|
||||
"is_verified": false,
|
||||
"created_at": "2024-10-27T11:00:00Z"
|
||||
}
|
||||
],
|
||||
"page_state": "base64_encoded_pagination_token"
|
||||
}
|
||||
```
|
||||
|
||||
**Notes**:
|
||||
- Returns a summary view (limited fields) for performance
|
||||
- Use `page_state` for pagination through large result sets
|
||||
- Sites are ordered by creation date (newest first)
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**401 Unauthorized**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to retrieve sites"
|
||||
}
|
||||
```
|
||||
99
cloud/maplepress-backend/docs/API/login.md
Normal file
99
cloud/maplepress-backend/docs/API/login.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# Login
|
||||
|
||||
**POST /api/v1/login**
|
||||
|
||||
Authenticate an existing user and obtain authentication tokens. This endpoint validates user credentials and creates a new session.
|
||||
|
||||
**Authentication**: None required (public endpoint)
|
||||
|
||||
**Headers**:
|
||||
- `Content-Type: application/json`
|
||||
|
||||
**Request Body**:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| email | string | Yes | User's email address |
|
||||
| password | string | Yes | User's password |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "john@example.com",
|
||||
"password": "SecurePassword123!"
|
||||
}'
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"user_email": "john@example.com",
|
||||
"user_name": "John Doe",
|
||||
"user_role": "user",
|
||||
"tenant_id": "650e8400-e29b-41d4-a716-446655440000",
|
||||
"session_id": "750e8400-e29b-41d4-a716-446655440000",
|
||||
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"access_expiry": "2024-10-24T12:15:00Z",
|
||||
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"refresh_expiry": "2024-10-31T00:00:00Z",
|
||||
"login_at": "2024-10-24T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**400 Bad Request** - Invalid input:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Bad Request",
|
||||
"status": 400,
|
||||
"detail": "Invalid request body format. Please check your JSON syntax."
|
||||
}
|
||||
```
|
||||
|
||||
**401 Unauthorized** - Invalid credentials:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Invalid email or password."
|
||||
}
|
||||
```
|
||||
|
||||
**429 Too Many Requests** - Rate limit exceeded:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Too Many Requests",
|
||||
"status": 429,
|
||||
"detail": "Too many login attempts from this IP address. Please try again later."
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to process login. Please try again later."
|
||||
}
|
||||
```
|
||||
|
||||
**Notes**:
|
||||
- The `tenant_id` is required for multi-tenant authentication to ensure user credentials are validated within the correct tenant context
|
||||
- Access tokens expire after 15 minutes
|
||||
- Refresh tokens expire after 7 days
|
||||
- Both tokens are JWT tokens that should be stored securely on the client side
|
||||
- Use the access token in the `Authorization: JWT {token}` header for authenticated requests
|
||||
73
cloud/maplepress-backend/docs/API/plugin-verify-api-key.md
Normal file
73
cloud/maplepress-backend/docs/API/plugin-verify-api-key.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# Verify API Key (WordPress Plugin)
|
||||
|
||||
**GET /api/v1/plugin/status**
|
||||
|
||||
Verify that an API key is valid and retrieve site information. This endpoint is used by the WordPress plugin to verify the connection and display quota information.
|
||||
|
||||
**Authentication**: Required (API Key)
|
||||
|
||||
**Headers**:
|
||||
- `Authorization: Bearer {api_key}`
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:8000/api/v1/plugin/status \
|
||||
-H "Authorization: Bearer live_sk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0"
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"site_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||
"tenant_id": "t1t2t3t4-t5t6-7890-tttt-tttttttttttt",
|
||||
"domain": "example.com",
|
||||
"site_url": "https://example.com",
|
||||
"status": "active",
|
||||
"is_verified": true,
|
||||
"storage_used_bytes": 52428800,
|
||||
"search_requests_count": 234,
|
||||
"monthly_pages_indexed": 50,
|
||||
"total_pages_indexed": 145,
|
||||
"search_index_name": "site_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||
"api_key_prefix": "live_sk_a1b2",
|
||||
"api_key_last_four": "s9t0",
|
||||
"plugin_version": "1.0.0",
|
||||
"message": "API key is valid"
|
||||
}
|
||||
```
|
||||
|
||||
**Notes**:
|
||||
- Used by WordPress plugin to verify connection on plugin activation
|
||||
- Returns site information and usage tracking statistics
|
||||
- If the API key is invalid or missing, returns 401 Unauthorized
|
||||
- Usage-based billing: No quotas or limits, only usage tracking for billing
|
||||
- If the request reaches this handler, the API key has already been validated by the middleware
|
||||
- API key must start with `live_sk_` or `test_sk_` prefix
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**401 Unauthorized** - Invalid or missing API key:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Invalid or missing API key"
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to verify API key"
|
||||
}
|
||||
```
|
||||
131
cloud/maplepress-backend/docs/API/refresh-token.md
Normal file
131
cloud/maplepress-backend/docs/API/refresh-token.md
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
# Refresh Token
|
||||
|
||||
**POST /api/v1/refresh**
|
||||
|
||||
Obtain a new access token and refresh token using an existing valid refresh token. This endpoint should be called when the access token expires (after 15 minutes) to maintain the user's session without requiring them to log in again.
|
||||
|
||||
**Authentication**: None required (public endpoint, but requires valid refresh token)
|
||||
|
||||
**Headers**:
|
||||
- `Content-Type: application/json`
|
||||
|
||||
**Request Body**:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| refresh_token | string | Yes | Valid refresh token from login or previous refresh |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/refresh \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
}'
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"user_email": "john@example.com",
|
||||
"user_name": "John Doe",
|
||||
"user_role": "user",
|
||||
"tenant_id": "650e8400-e29b-41d4-a716-446655440000",
|
||||
"session_id": "750e8400-e29b-41d4-a716-446655440000",
|
||||
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"access_expiry": "2024-10-24T12:30:00Z",
|
||||
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"refresh_expiry": "2024-10-31T00:15:00Z",
|
||||
"refreshed_at": "2024-10-24T12:15:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**400 Bad Request** - Missing refresh token:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Bad Request",
|
||||
"status": 400,
|
||||
"detail": "Refresh token is required"
|
||||
}
|
||||
```
|
||||
|
||||
**401 Unauthorized** - Invalid or expired refresh token:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Invalid or expired refresh token. Please log in again."
|
||||
}
|
||||
```
|
||||
|
||||
**401 Unauthorized** - Session invalidated:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Session has expired or been invalidated. Please log in again."
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to refresh token. Please try again later."
|
||||
}
|
||||
```
|
||||
|
||||
**Token Refresh Flow**:
|
||||
|
||||
1. **Initial Authentication**: User logs in via `/api/v1/login` and receives:
|
||||
- Access token (expires in 15 minutes)
|
||||
- Refresh token (expires in 7 days)
|
||||
|
||||
2. **Token Usage**: Client uses the access token for API requests
|
||||
|
||||
3. **Token Expiration**: When access token expires (after 15 minutes):
|
||||
- Client detects 401 Unauthorized response
|
||||
- Client calls `/api/v1/refresh` with the refresh token
|
||||
- Server validates refresh token and session
|
||||
- Server returns new access token and new refresh token
|
||||
|
||||
4. **Token Rotation**: Both tokens are regenerated on refresh:
|
||||
- New access token (valid for 15 minutes from refresh time)
|
||||
- New refresh token (valid for 7 days from refresh time)
|
||||
- Old tokens become invalid
|
||||
|
||||
5. **Session Validation**: The refresh token is validated against the active session:
|
||||
- If the session has been deleted (e.g., user logged out), refresh will fail
|
||||
- If the session has expired (after 14 days of inactivity), refresh will fail
|
||||
- This prevents using refresh tokens after logout
|
||||
|
||||
**Best Practices**:
|
||||
|
||||
- Store both access and refresh tokens securely on the client (e.g., secure HTTP-only cookies or encrypted storage)
|
||||
- Implement automatic token refresh when access token expires (don't wait for 401 errors)
|
||||
- Consider refreshing tokens proactively before expiration (e.g., 1 minute before)
|
||||
- Handle refresh failures by redirecting user to login
|
||||
- Never share refresh tokens across devices or sessions
|
||||
- Clear tokens on logout
|
||||
|
||||
**Security Notes**:
|
||||
|
||||
- Refresh tokens are single-use in practice due to token rotation
|
||||
- Each refresh generates a new token pair and invalidates the old one
|
||||
- Session validation prevents token reuse after logout (CWE-613)
|
||||
- Refresh tokens have a longer lifetime but are still time-limited (7 days)
|
||||
- Sessions expire after 14 days of inactivity regardless of token refresh
|
||||
149
cloud/maplepress-backend/docs/API/register.md
Normal file
149
cloud/maplepress-backend/docs/API/register.md
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
# Register User & Tenant
|
||||
|
||||
**POST /api/v1/register**
|
||||
|
||||
Register a new user and create a new tenant (organization) in a single request. This is the primary onboarding endpoint that returns authentication tokens.
|
||||
|
||||
**Authentication**: None required (public endpoint)
|
||||
|
||||
**Headers**:
|
||||
- `Content-Type: application/json`
|
||||
|
||||
**Request Body**:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| email | string | Yes | User's email address |
|
||||
| password | string | Yes | User's password (min 8 characters) |
|
||||
| confirm_password | string | Yes | Password confirmation (must match password) |
|
||||
| first_name | string | Yes | User's first name |
|
||||
| last_name | string | Yes | User's last name |
|
||||
| tenant_name | string | Yes | Organization/tenant name (slug auto-generated from this) |
|
||||
| timezone | string | No | User's timezone (e.g., "America/New_York", defaults to "UTC" if not provided) |
|
||||
| agree_terms_of_service | boolean | Yes | Must be true - user agreement to Terms of Service |
|
||||
| agree_promotions | boolean | No | Optional - user agreement to receive promotional emails (default: false) |
|
||||
| agree_to_tracking_across_third_party_apps_and_services | boolean | No | Optional - user agreement to cross-platform tracking (default: false) |
|
||||
|
||||
**Example Request (with timezone)**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/register \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "john@example.com",
|
||||
"password": "SecurePassword123!",
|
||||
"confirm_password": "SecurePassword123!",
|
||||
"first_name": "John",
|
||||
"last_name": "Doe",
|
||||
"tenant_name": "Acme Corporation",
|
||||
"timezone": "America/New_York",
|
||||
"agree_terms_of_service": true,
|
||||
"agree_promotions": false,
|
||||
"agree_to_tracking_across_third_party_apps_and_services": false
|
||||
}'
|
||||
```
|
||||
|
||||
**Example Request (without timezone - defaults to UTC)**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/register \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "jane@example.com",
|
||||
"password": "SecurePassword456!",
|
||||
"confirm_password": "SecurePassword456!",
|
||||
"first_name": "Jane",
|
||||
"last_name": "Smith",
|
||||
"tenant_name": "Beta Inc",
|
||||
"agree_terms_of_service": true
|
||||
}'
|
||||
```
|
||||
|
||||
**Example Response** (201 Created):
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"user_email": "john@example.com",
|
||||
"user_name": "John Doe",
|
||||
"user_role": "manager",
|
||||
"tenant_id": "650e8400-e29b-41d4-a716-446655440000",
|
||||
"tenant_name": "Acme Corporation",
|
||||
"tenant_slug": "acme-corp",
|
||||
"session_id": "750e8400-e29b-41d4-a716-446655440000",
|
||||
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"access_expiry": "2024-10-24T12:00:00Z",
|
||||
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"refresh_expiry": "2024-11-24T00:00:00Z",
|
||||
"created_at": "2024-10-24T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Validation Error Response** (400 Bad Request):
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Validation Error",
|
||||
"status": 400,
|
||||
"detail": "One or more validation errors occurred",
|
||||
"errors": {
|
||||
"email": ["Invalid email format"],
|
||||
"password": ["Field is required", "Password must be at least 8 characters"],
|
||||
"confirm_password": ["Field is required", "Passwords do not match"],
|
||||
"first_name": ["Field is required"],
|
||||
"last_name": ["Field is required"],
|
||||
"tenant_name": ["Field is required"],
|
||||
"agree_terms_of_service": ["Must agree to terms of service"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**Common Validation Error Messages**:
|
||||
|
||||
| Field | Error Messages |
|
||||
|-------|---------------|
|
||||
| email | "Invalid email format", "Field is required" |
|
||||
| password | "Field is required", "Password must be at least 8 characters", "Password must contain at least one uppercase letter (A-Z)", "Password must contain at least one lowercase letter (a-z)", "Password must contain at least one number (0-9)", "Password must contain at least one special character" |
|
||||
| confirm_password | "Field is required", "Passwords do not match" |
|
||||
| first_name | "Field is required", "First_name must be between 1 and 100 characters" |
|
||||
| last_name | "Field is required", "Last_name must be between 1 and 100 characters" |
|
||||
| tenant_name | "Field is required", "Tenant_name must be between 1 and 100 characters" |
|
||||
| agree_terms_of_service | "Must agree to terms of service" |
|
||||
|
||||
**Other Error Responses**:
|
||||
|
||||
- `409 Conflict`: Email or tenant slug already exists
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Conflict",
|
||||
"status": 409,
|
||||
"detail": "Registration failed. The provided information is already in use"
|
||||
}
|
||||
```
|
||||
|
||||
- `500 Internal Server Error`: Server error
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to register user"
|
||||
}
|
||||
```
|
||||
|
||||
**Important Notes**:
|
||||
- `agree_terms_of_service` must be `true` or the request will fail with 400 Bad Request
|
||||
- `first_name` and `last_name` are required fields
|
||||
- `timezone` is optional and defaults to "UTC" if not provided
|
||||
- Password must be at least 8 characters long
|
||||
- **Tenant slug is automatically generated** from `tenant_name` (converted to lowercase, special chars replaced with hyphens)
|
||||
- The IP address of the request is automatically captured for audit trail purposes
|
||||
- User role for registration is always "manager" (tenant creator)
|
||||
79
cloud/maplepress-backend/docs/API/rotate-site-api-key.md
Normal file
79
cloud/maplepress-backend/docs/API/rotate-site-api-key.md
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# Rotate Site API Key
|
||||
|
||||
**POST /api/v1/sites/{id}/rotate-api-key**
|
||||
|
||||
Rotate a site's API key (use when the key is compromised).
|
||||
|
||||
**Authentication**: Required (JWT Bearer token)
|
||||
|
||||
**Headers**:
|
||||
- `Authorization: JWT {access_token}`
|
||||
|
||||
**URL Parameters**:
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| id | UUID | Yes | Site ID |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/sites/a1b2c3d4-e5f6-7890-abcd-ef1234567890/rotate-api-key \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"new_api_key": "live_sk_z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5k4j3i2h1g0",
|
||||
"old_key_last_four": "s9t0",
|
||||
"rotated_at": "2024-10-27T15:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**🚨 CRITICAL Notes**:
|
||||
- The `new_api_key` is shown **only once** - save it immediately!
|
||||
- The old API key is **immediately invalidated** - no grace period!
|
||||
- Your WordPress site will stop working until you update the plugin with the new key
|
||||
- Update the WordPress plugin settings **RIGHT NOW** to restore functionality
|
||||
- The rotation happens atomically:
|
||||
- Old key is deleted from the database
|
||||
- New key is inserted into the database
|
||||
- Both operations complete instantly
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**401 Unauthorized**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Authentication required"
|
||||
}
|
||||
```
|
||||
|
||||
**404 Not Found**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Not Found",
|
||||
"status": 404,
|
||||
"detail": "Site not found or doesn't belong to your tenant"
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error**:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to rotate API key"
|
||||
}
|
||||
```
|
||||
148
cloud/maplepress-backend/docs/API/verify-site.md
Normal file
148
cloud/maplepress-backend/docs/API/verify-site.md
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
# Verify WordPress Site
|
||||
|
||||
**POST /api/v1/sites/{id}/verify**
|
||||
|
||||
Verify a WordPress site by checking DNS TXT records to prove domain ownership. This transitions the site from `pending` to `active` status.
|
||||
|
||||
**Authentication**: Required (JWT Bearer token)
|
||||
|
||||
**Headers**:
|
||||
- `Authorization: JWT {access_token}`
|
||||
|
||||
**URL Parameters**:
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| id | UUID | Yes | Site ID |
|
||||
|
||||
**Request Body**:
|
||||
|
||||
No request body required. Verification is done automatically by checking DNS TXT records.
|
||||
|
||||
**DNS TXT Record Setup**:
|
||||
|
||||
Before calling this endpoint, you must add a DNS TXT record to your domain:
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Host/Name | Your domain (e.g., `example.com`) |
|
||||
| Type | TXT |
|
||||
| Value | `maplepress-verify={verification_token}` |
|
||||
|
||||
The verification token is provided when you create the site. DNS propagation typically takes 5-10 minutes but can take up to 48 hours.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/sites/a1b2c3d4-e5f6-7890-abcd-ef1234567890/verify \
|
||||
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
```
|
||||
|
||||
**Example Response** (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"status": "active",
|
||||
"message": "Domain ownership verified successfully via DNS TXT record"
|
||||
}
|
||||
```
|
||||
|
||||
**Important Notes**:
|
||||
- The verification token is provided when the site is created (POST /api/v1/sites)
|
||||
- You must add the DNS TXT record to your domain before calling this endpoint
|
||||
- DNS propagation typically takes 5-10 minutes but can take up to 48 hours
|
||||
- Once verified, the site status changes from `pending` to `active`
|
||||
- After verification, the site can sync pages and use search functionality
|
||||
- Test mode sites (`test_sk_` API keys) skip DNS verification automatically
|
||||
- Already verified sites return success without error
|
||||
|
||||
**Verification Flow**:
|
||||
1. User creates site via dashboard → receives `verification_token` and DNS instructions
|
||||
2. User adds DNS TXT record to domain registrar: `maplepress-verify={token}`
|
||||
3. User waits 5-10 minutes for DNS propagation
|
||||
4. User clicks "Verify Site" in plugin → calls this endpoint
|
||||
5. Backend performs DNS TXT lookup to verify domain ownership
|
||||
6. Site transitions to `active` status → full functionality enabled
|
||||
|
||||
**Error Responses**:
|
||||
|
||||
This endpoint returns errors in **RFC 9457 (Problem Details for HTTP APIs)** format.
|
||||
|
||||
**Content-Type**: `application/problem+json`
|
||||
|
||||
**400 Bad Request** - DNS TXT record not found:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Bad Request",
|
||||
"status": 400,
|
||||
"detail": "DNS TXT record not found. Please add the verification record to your domain's DNS settings and wait 5-10 minutes for propagation."
|
||||
}
|
||||
```
|
||||
|
||||
**400 Bad Request** - DNS lookup timed out:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Bad Request",
|
||||
"status": 400,
|
||||
"detail": "DNS lookup timed out. Please check that your domain's DNS is properly configured."
|
||||
}
|
||||
```
|
||||
|
||||
**400 Bad Request** - Domain not found:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Bad Request",
|
||||
"status": 400,
|
||||
"detail": "Domain not found. Please check that your domain is properly registered and DNS is active."
|
||||
}
|
||||
```
|
||||
|
||||
**400 Bad Request** - Invalid site ID:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Bad Request",
|
||||
"status": 400,
|
||||
"detail": "Invalid site ID format. Please provide a valid site ID."
|
||||
}
|
||||
```
|
||||
|
||||
**401 Unauthorized** - Missing or invalid JWT:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Tenant context is required to access this resource."
|
||||
}
|
||||
```
|
||||
|
||||
**404 Not Found** - Site not found or doesn't belong to tenant:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Not Found",
|
||||
"status": 404,
|
||||
"detail": "The requested site could not be found. It may have been deleted or you may not have access to it."
|
||||
}
|
||||
```
|
||||
|
||||
**500 Internal Server Error** - Server error:
|
||||
```json
|
||||
{
|
||||
"type": "about:blank",
|
||||
"title": "Internal Server Error",
|
||||
"status": 500,
|
||||
"detail": "Failed to verify site. Please try again later."
|
||||
}
|
||||
```
|
||||
|
||||
**Related Endpoints**:
|
||||
- [Create Site](./create-site.md) - Initial site creation (provides verification token)
|
||||
- [Get Site](./get-site.md) - Check verification status
|
||||
- [Plugin Status](./plugin-verify-api-key.md) - Check verification status from plugin
|
||||
- [Sync Pages](./plugin-sync-pages.md) - Requires verification
|
||||
Loading…
Add table
Add a link
Reference in a new issue