# API Endpoints Reference Complete reference for all core-api endpoints. All endpoints follow RESTful conventions with consistent authentication, pagination, filtering, and error handling. ## Base URL ``` https://your-domain.com/api/v1 ``` ## Authentication All authenticated endpoints require an API key in the Authorization header: ```http Authorization: Bearer sk_live_abc123def456... ``` See [Authentication](/packages/api/authentication) for details on creating and managing API keys. ## Common Headers ### Request Headers | Header | Required | Description | |--------|----------|-------------| | `Authorization` | Yes* | API key (Bearer token) | | `Accept` | No | Should be `application/json` | | `Content-Type` | For POST/PUT | Should be `application/json` | | `X-Workspace-ID` | Sometimes | Workspace context for multi-tenant endpoints | | `Idempotency-Key` | No | UUID for safe retries on POST/PUT/DELETE | *Required for authenticated endpoints ### Response Headers | Header | Description | |--------|-------------| | `X-RateLimit-Limit` | Maximum requests allowed in window | | `X-RateLimit-Remaining` | Requests remaining in current window | | `X-RateLimit-Reset` | Unix timestamp when limit resets | | `X-Request-ID` | Unique request identifier for debugging | ## Common Parameters ### Pagination All list endpoints support pagination: | Parameter | Type | Default | Max | Description | |-----------|------|---------|-----|-------------| | `page` | integer | 1 | - | Page number | | `per_page` | integer | 25 | 100 | Items per page | **Response format:** ```json { "data": [...], "meta": { "current_page": 1, "from": 1, "last_page": 10, "per_page": 25, "to": 25, "total": 250 }, "links": { "first": "https://api.example.com/v1/resource?page=1", "last": "https://api.example.com/v1/resource?page=10", "prev": null, "next": "https://api.example.com/v1/resource?page=2" } } ``` ### Filtering Filter list results with query parameters: | Parameter | Type | Description | |-----------|------|-------------| | `status` | string | Filter by status (varies by resource) | | `created_after` | ISO 8601 date | Filter by creation date | | `created_before` | ISO 8601 date | Filter by creation date | | `updated_after` | ISO 8601 date | Filter by update date | | `updated_before` | ISO 8601 date | Filter by update date | | `search` | string | Full-text search (if supported) | ### Sorting Sort results using the `sort` parameter: ```http GET /api/v1/resources?sort=-created_at,name ``` - Prefix with `-` for descending order - Default is ascending order - Comma-separate multiple fields ### Field Selection Request specific fields only: ```http GET /api/v1/resources?fields=id,name,created_at ``` ### Includes Eager-load related resources: ```http GET /api/v1/resources?include=owner,tags ``` --- ## Workspaces ### List Workspaces ```http GET /api/v1/workspaces ``` **Required scope:** `workspaces:read` **Query parameters:** | Parameter | Type | Description | |-----------|------|-------------| | `page` | integer | Page number | | `per_page` | integer | Items per page | **Response:** `200 OK` ```json { "data": [ { "id": 1, "name": "Acme Corporation", "slug": "acme-corp", "tier": "business", "created_at": "2026-01-01T00:00:00Z", "updated_at": "2026-01-15T10:30:00Z" } ], "meta": {...}, "links": {...} } ``` ### Get Workspace ```http GET /api/v1/workspaces/{id} ``` **Required scope:** `workspaces:read` **Path parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `id` | integer | Yes | Workspace ID | **Response:** `200 OK` ```json { "data": { "id": 1, "name": "Acme Corporation", "slug": "acme-corp", "tier": "business", "settings": { "timezone": "UTC", "locale": "en_GB" }, "created_at": "2026-01-01T00:00:00Z", "updated_at": "2026-01-15T10:30:00Z" } } ``` **Error responses:** | Status | Code | Description | |--------|------|-------------| | 404 | `not_found` | Workspace not found | ### Create Workspace ```http POST /api/v1/workspaces ``` **Required scope:** `workspaces:write` **Request body:** ```json { "name": "New Workspace", "slug": "new-workspace", "tier": "pro" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `name` | string | Yes | Workspace name (max 255 chars) | | `slug` | string | No | URL-friendly identifier (auto-generated if not provided) | | `tier` | string | No | Subscription tier (default: free) | **Response:** `201 Created` ```json { "message": "Workspace created successfully.", "data": { "id": 2, "name": "New Workspace", "slug": "new-workspace", "tier": "pro", "created_at": "2026-01-15T10:30:00Z" } } ``` **Error responses:** | Status | Code | Description | |--------|------|-------------| | 422 | `validation_failed` | Invalid input data | ### Update Workspace ```http PATCH /api/v1/workspaces/{id} ``` **Required scope:** `workspaces:write` **Request body:** ```json { "name": "Updated Name", "settings": { "timezone": "Europe/London" } } ``` **Response:** `200 OK` ### Delete Workspace ```http DELETE /api/v1/workspaces/{id} ``` **Required scope:** `workspaces:delete` **Response:** `204 No Content` --- ## API Keys ### List API Keys ```http GET /api/v1/api-keys ``` **Required scope:** `api-keys:read` **Response:** `200 OK` ```json { "data": [ { "id": 1, "name": "Production API Key", "prefix": "sk_live_abc", "scopes": ["posts:read", "posts:write"], "rate_limit_tier": "pro", "last_used_at": "2026-01-15T10:30:00Z", "expires_at": null, "created_at": "2026-01-01T00:00:00Z" } ] } ``` Note: The full API key is never returned after creation. ### Get API Key ```http GET /api/v1/api-keys/{id} ``` **Required scope:** `api-keys:read` **Response:** `200 OK` ```json { "data": { "id": 1, "name": "Production API Key", "prefix": "sk_live_abc", "scopes": ["posts:read", "posts:write"], "rate_limit_tier": "pro", "last_used_at": "2026-01-15T10:30:00Z", "expires_at": null, "created_at": "2026-01-01T00:00:00Z" } } ``` ### Create API Key ```http POST /api/v1/api-keys ``` **Required scope:** `api-keys:write` **Request body:** ```json { "name": "Mobile App Key", "scopes": ["posts:read", "users:read"], "rate_limit_tier": "pro", "expires_at": "2027-01-01T00:00:00Z" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `name` | string | Yes | Key name (max 255 chars) | | `scopes` | array | No | Permission scopes (default: read, write) | | `rate_limit_tier` | string | No | Rate limit tier (default: from workspace) | | `expires_at` | ISO 8601 | No | Expiration date (null = never) | **Response:** `201 Created` ```json { "message": "API key created successfully.", "data": { "id": 2, "name": "Mobile App Key", "key": "sk_live_abc123def456ghi789...", "scopes": ["posts:read", "users:read"], "rate_limit_tier": "pro", "expires_at": "2027-01-01T00:00:00Z", "created_at": "2026-01-15T10:30:00Z" } } ``` **Important:** The `key` field is only returned once during creation. Store it securely. ### Rotate API Key ```http POST /api/v1/api-keys/{id}/rotate ``` **Required scope:** `api-keys:write` **Request body:** ```json { "grace_period_hours": 24 } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `grace_period_hours` | integer | No | Hours both keys work (default: 24) | **Response:** `200 OK` ```json { "message": "API key rotated successfully.", "data": { "id": 3, "name": "Mobile App Key", "key": "sk_live_new123key456...", "scopes": ["posts:read", "users:read"], "grace_period_ends_at": "2026-01-16T10:30:00Z" } } ``` ### Revoke API Key ```http DELETE /api/v1/api-keys/{id} ``` **Required scope:** `api-keys:delete` **Response:** `204 No Content` --- ## Webhooks ### List Webhook Endpoints ```http GET /api/v1/webhooks ``` **Required scope:** `webhooks:read` **Response:** `200 OK` ```json { "data": [ { "id": 1, "url": "https://your-app.com/webhooks", "events": ["post.created", "post.updated"], "is_active": true, "success_count": 150, "failure_count": 2, "last_delivery_at": "2026-01-15T10:30:00Z", "created_at": "2026-01-01T00:00:00Z" } ] } ``` ### Get Webhook Endpoint ```http GET /api/v1/webhooks/{id} ``` **Required scope:** `webhooks:read` **Response:** `200 OK` ```json { "data": { "id": 1, "url": "https://your-app.com/webhooks", "events": ["post.created", "post.updated"], "is_active": true, "success_count": 150, "failure_count": 2, "consecutive_failures": 0, "last_delivery_at": "2026-01-15T10:30:00Z", "created_at": "2026-01-01T00:00:00Z" } } ``` ### Create Webhook Endpoint ```http POST /api/v1/webhooks ``` **Required scope:** `webhooks:write` **Request body:** ```json { "url": "https://your-app.com/webhooks", "events": ["post.created", "post.updated", "post.deleted"], "secret": "whsec_abc123def456..." } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `url` | string | Yes | Webhook endpoint URL (HTTPS required) | | `events` | array | Yes | Events to subscribe to | | `secret` | string | No | Signing secret (auto-generated if not provided) | **Response:** `201 Created` ```json { "message": "Webhook endpoint created successfully.", "data": { "id": 2, "url": "https://your-app.com/webhooks", "events": ["post.created", "post.updated", "post.deleted"], "secret": "whsec_abc123def456...", "is_active": true, "created_at": "2026-01-15T10:30:00Z" } } ``` **Important:** The `secret` is only returned during creation. Store it securely. ### Update Webhook Endpoint ```http PATCH /api/v1/webhooks/{id} ``` **Required scope:** `webhooks:write` **Request body:** ```json { "url": "https://new-url.com/webhooks", "events": ["post.*"], "is_active": true } ``` **Response:** `200 OK` ### Delete Webhook Endpoint ```http DELETE /api/v1/webhooks/{id} ``` **Required scope:** `webhooks:delete` **Response:** `204 No Content` ### Test Webhook Endpoint ```http POST /api/v1/webhooks/{id}/test ``` **Required scope:** `webhooks:write` Sends a test event to the webhook endpoint. **Response:** `200 OK` ```json { "success": true, "status_code": 200, "response_time_ms": 145, "response_body": "{\"received\": true}" } ``` **Error response (delivery failed):** ```json { "success": false, "status_code": 500, "error": "Connection timeout", "response_time_ms": 30000 } ``` ### List Webhook Deliveries ```http GET /api/v1/webhooks/{id}/deliveries ``` **Required scope:** `webhooks:read` **Query parameters:** | Parameter | Type | Description | |-----------|------|-------------| | `status` | string | Filter by status: `pending`, `success`, `failed`, `retrying` | | `page` | integer | Page number | | `per_page` | integer | Items per page | **Response:** `200 OK` ```json { "data": [ { "id": 1, "event_id": "evt_abc123def456", "event_type": "post.created", "status": "success", "response_code": 200, "attempt": 1, "delivered_at": "2026-01-15T10:30:00Z", "created_at": "2026-01-15T10:30:00Z" }, { "id": 2, "event_id": "evt_xyz789", "event_type": "post.updated", "status": "retrying", "response_code": 500, "attempt": 2, "next_retry_at": "2026-01-15T10:35:00Z", "created_at": "2026-01-15T10:30:00Z" } ], "meta": {...}, "links": {...} } ``` ### Retry Webhook Delivery ```http POST /api/v1/webhooks/{webhook_id}/deliveries/{delivery_id}/retry ``` **Required scope:** `webhooks:write` Manually retry a failed delivery. **Response:** `200 OK` ```json { "message": "Delivery queued for retry.", "data": { "id": 2, "status": "pending", "attempt": 3 } } ``` **Error responses:** | Status | Code | Description | |--------|------|-------------| | 400 | `cannot_retry` | Delivery already succeeded or max retries reached | --- ## Entitlements ### Check Feature Access ```http GET /api/v1/entitlements/check ``` **Required scope:** `entitlements:read` **Query parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `feature` | string | Yes | Feature key to check | | `quantity` | integer | No | Amount to check (default: 1) | **Response:** `200 OK` ```json { "allowed": true, "feature": "posts", "current_usage": 45, "limit": 100, "available": 55 } ``` **Response (limit exceeded):** ```json { "allowed": false, "feature": "posts", "reason": "LIMIT_EXCEEDED", "message": "Post limit exceeded. Used: 100, Limit: 100", "current_usage": 100, "limit": 100, "available": 0, "upgrade_url": "https://example.com/upgrade" } ``` ### Record Usage ```http POST /api/v1/entitlements/usage ``` **Required scope:** `entitlements:write` **Request body:** ```json { "feature": "api_calls", "quantity": 1, "metadata": { "endpoint": "/api/v1/posts" } } ``` **Response:** `200 OK` ```json { "recorded": true, "feature": "api_calls", "current_usage": 5001, "limit": 10000 } ``` ### Get Usage Summary ```http GET /api/v1/entitlements/summary ``` **Required scope:** `entitlements:read` Returns usage summary for the authenticated user's workspace. **Response:** `200 OK` ```json { "data": { "workspace_id": 1, "tier": "pro", "entitlements": { "posts": { "used": 45, "limit": 1000, "available": 955, "percentage": 4.5 }, "api_calls": { "used": 5001, "limit": 10000, "available": 4999, "percentage": 50.01, "reset_at": "2026-02-01T00:00:00Z" }, "storage": { "used": 1073741824, "limit": 5368709120, "available": 4294967296, "percentage": 20, "unit": "bytes" } } } } ``` --- ## SEO Reports ### Submit SEO Report ```http POST /api/v1/seo/report ``` **Required scope:** `seo:write` **Request body:** ```json { "url": "https://example.com/page", "scores": { "performance": 85, "accessibility": 92, "best_practices": 88, "seo": 95 }, "issues": [ { "type": "missing_alt", "severity": "warning", "element": "img.hero-image" } ] } ``` **Response:** `201 Created` ### Get SEO Issues ```http GET /api/v1/seo/issues/{workspace_id} ``` **Required scope:** `seo:read` **Response:** `200 OK` ```json { "data": [ { "id": 1, "url": "https://example.com/page", "issue_type": "missing_alt", "severity": "warning", "details": {...}, "created_at": "2026-01-15T10:30:00Z" } ] } ``` --- ## Pixel Tracking ### Get Pixel Configuration ```http GET /api/v1/pixel/config ``` **Authentication:** Not required Returns tracking pixel configuration for the current domain. **Response:** `200 OK` ```json { "enabled": true, "features": { "pageviews": true, "events": true, "sessions": true }, "sample_rate": 1.0 } ``` ### Track Event ```http POST /api/v1/pixel/track ``` **Authentication:** Not required **Rate limit:** 300 requests per minute **Request body:** ```json { "event": "pageview", "url": "https://example.com/page", "referrer": "https://google.com", "user_agent": "Mozilla/5.0...", "properties": { "title": "Page Title" } } ``` **Response:** `200 OK` ```json { "tracked": true } ``` --- ## MCP (Model Context Protocol) ### List MCP Servers ```http GET /api/v1/mcp/servers ``` **Required scope:** `mcp:read` **Response:** `200 OK` ```json { "data": [ { "id": "filesystem", "name": "Filesystem Server", "description": "File and directory operations", "tools": ["read_file", "write_file", "list_directory"] } ] } ``` ### Get MCP Server ```http GET /api/v1/mcp/servers/{id} ``` **Required scope:** `mcp:read` ### List Server Tools ```http GET /api/v1/mcp/servers/{id}/tools ``` **Required scope:** `mcp:read` **Response:** `200 OK` ```json { "data": [ { "name": "read_file", "description": "Read contents of a file", "parameters": { "path": { "type": "string", "description": "File path to read", "required": true } } } ] } ``` ### Call MCP Tool ```http POST /api/v1/mcp/tools/call ``` **Required scope:** `mcp:write` **Request body:** ```json { "server": "filesystem", "tool": "read_file", "arguments": { "path": "/path/to/file.txt" } } ``` **Response:** `200 OK` ```json { "result": { "content": "File contents here...", "size": 1234 } } ``` ### Get MCP Resource ```http GET /api/v1/mcp/resources/{uri} ``` **Required scope:** `mcp:read` The `uri` can include slashes and will be URL-decoded. --- ## Error Responses All errors follow a consistent format: ### Validation Error (422) ```json { "error": "validation_failed", "message": "The given data was invalid.", "errors": { "name": ["The name field is required."], "email": ["The email must be a valid email address."] } } ``` ### Not Found (404) ```json { "error": "not_found", "message": "Resource not found." } ``` ### Unauthorized (401) ```json { "error": "unauthorized", "message": "Invalid or missing API key." } ``` ### Forbidden (403) ```json { "error": "access_denied", "message": "Insufficient permissions. Required scope: posts:write" } ``` ### Feature Limit Reached (403) ```json { "error": "feature_limit_reached", "message": "You have reached your limit for this feature.", "feature": "posts", "upgrade_url": "https://example.com/upgrade" } ``` ### Rate Limited (429) ```json { "error": "rate_limit_exceeded", "message": "Too many requests. Please retry after 60 seconds.", "retry_after": 60, "limit": 1000, "remaining": 0, "reset_at": "2026-01-15T11:00:00Z" } ``` ### Server Error (500) ```json { "error": "server_error", "message": "An unexpected error occurred.", "request_id": "req_abc123def456" } ``` --- ## Rate Limits Rate limits vary by tier: | Tier | Requests/Minute | Burst Allowance | |------|-----------------|-----------------| | Free | 60 | None | | Starter | 1,000 | 20% | | Pro | 5,000 | 30% | | Agency | 20,000 | 50% | | Enterprise | 100,000 | 100% | Rate limit headers are included in every response: ```http X-RateLimit-Limit: 5000 X-RateLimit-Remaining: 4892 X-RateLimit-Reset: 1705312260 ``` See [Rate Limiting](/packages/api/rate-limiting) for details. --- ## Idempotency For safe retries on POST, PUT, and DELETE requests, include an idempotency key: ```http POST /api/v1/posts Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000 ``` If the same idempotency key is used within 24 hours: - Same status code and response body returned - No duplicate resource created - Safe to retry failed requests --- ## Learn More - [Building REST APIs](/packages/api/building-rest-apis) - Tutorial for creating API endpoints - [Authentication](/packages/api/authentication) - API key management - [Webhooks](/packages/api/webhooks) - Event notifications - [Webhook Integration](/packages/api/webhook-integration) - Consumer guide - [Rate Limiting](/packages/api/rate-limiting) - Understanding rate limits - [Scopes](/packages/api/scopes) - Permission system