API Reference
Authentication
Section titled “Authentication”All API requests require authentication using JWT tokens or API keys.
Getting an API Key
Section titled “Getting an API Key”- Navigate to the admin panel at
/admin
- Go to Settings → API Keys
- Click “Generate New Key” and copy the generated key
- Include the key in your requests using the
Authorization
header
Authorization: Bearer your-api-key-here
REST API
Section titled “REST API”The REST API follows RESTful conventions and returns JSON responses.
Base URL
Section titled “Base URL”https://your-domain.com/api
Content Operations
Section titled “Content Operations”Get All Records
Section titled “Get All Records”GET /api/{model}
Parameters:
limit
(number): Number of records to return (default: 20, max: 100)offset
(number): Number of records to skip (default: 0)sort
(string): Field to sort by (prefix with-
for descending)filter
(object): Filtering conditionspopulate
(string[]): Related fields to include
Example:
curl -X GET "https://your-domain.com/api/blogPost?limit=10&sort=-publishedAt&populate=author,categories" \ -H "Authorization: Bearer your-api-key"
Response:
{ "data": [ { "id": "1", "title": "My First Blog Post", "slug": "my-first-blog-post", "content": "<p>This is the content...</p>", "publishedAt": "2024-01-15T10:00:00Z", "author": { "id": "1", "name": "John Doe", "email": "john@example.com" }, "categories": [ { "id": "1", "name": "Technology", "slug": "technology" } ] } ], "meta": { "total": 150, "limit": 10, "offset": 0, "hasMore": true }}
Get Single Record
Section titled “Get Single Record”GET /api/{model}/{id}
Example:
curl -X GET "https://your-domain.com/api/blogPost/1?populate=author" \ -H "Authorization: Bearer your-api-key"
Create Record
Section titled “Create Record”POST /api/{model}
Example:
curl -X POST "https://your-domain.com/api/blogPost" \ -H "Authorization: Bearer your-api-key" \ -H "Content-Type: application/json" \ -d '{ "title": "New Blog Post", "content": "<p>This is the content</p>", "status": "published" }'
Update Record
Section titled “Update Record”PUT /api/{model}/{id}PATCH /api/{model}/{id}
Example:
curl -X PATCH "https://your-domain.com/api/blogPost/1" \ -H "Authorization: Bearer your-api-key" \ -H "Content-Type: application/json" \ -d '{ "title": "Updated Blog Post Title" }'
Delete Record
Section titled “Delete Record”DELETE /api/{model}/{id}
Example:
curl -X DELETE "https://your-domain.com/api/blogPost/1" \ -H "Authorization: Bearer your-api-key"
Advanced Filtering
Section titled “Advanced Filtering”Use the filter
parameter for complex queries:
# Filter by statusGET /api/blogPost?filter[status]=published
# Filter by date rangeGET /api/blogPost?filter[publishedAt][$gte]=2024-01-01&filter[publishedAt][$lt]=2024-02-01
# Filter by related fieldGET /api/blogPost?filter[author.name]=John Doe
# Multiple conditionsGET /api/blogPost?filter[status]=published&filter[featured]=true
Filtering Operators
Section titled “Filtering Operators”Operator | Description | Example |
---|---|---|
$eq | Equal to | filter[status][$eq]=published |
$ne | Not equal to | filter[status][$ne]=draft |
$gt | Greater than | filter[views][$gt]=100 |
$gte | Greater than or equal | filter[publishedAt][$gte]=2024-01-01 |
$lt | Less than | filter[views][$lt]=1000 |
$lte | Less than or equal | filter[publishedAt][$lte]=2024-12-31 |
$in | In array | filter[status][$in]=published,featured |
$nin | Not in array | filter[status][$nin]=draft,archived |
$contains | Contains substring | filter[title][$contains]=tutorial |
$startsWith | Starts with | filter[slug][$startsWith]=how-to |
$endsWith | Ends with | filter[slug][$endsWith]=guide |
GraphQL API
Section titled “GraphQL API”GraphQL endpoint provides a flexible query language for fetching exactly the data you need.
Endpoint
Section titled “Endpoint”https://your-domain.com/graphql
Schema
Section titled “Schema”The GraphQL schema is automatically generated from your content models:
type BlogPost { id: ID! title: String! slug: String! content: String excerpt: String featuredImage: Image author: User categories: [Category!]! tags: [String!]! publishedAt: DateTime status: BlogPostStatus! featured: Boolean! createdAt: DateTime! updatedAt: DateTime!}
type Query { blogPost(id: ID!): BlogPost blogPosts( limit: Int = 20 offset: Int = 0 sort: String filter: BlogPostFilter ): BlogPostConnection!}
type Mutation { createBlogPost(data: CreateBlogPostInput!): BlogPost! updateBlogPost(id: ID!, data: UpdateBlogPostInput!): BlogPost! deleteBlogPost(id: ID!): Boolean!}
Query Examples
Section titled “Query Examples”Fetch Blog Posts
Section titled “Fetch Blog Posts”query GetBlogPosts { blogPosts(limit: 10, sort: "-publishedAt") { nodes { id title slug excerpt publishedAt author { id name avatar } categories { id name slug } } pageInfo { hasNextPage hasPreviousPage total } }}
Fetch Single Post
Section titled “Fetch Single Post”query GetBlogPost($id: ID!) { blogPost(id: $id) { id title content publishedAt author { name bio socialLinks } categories { name description } tags }}
Create New Post
Section titled “Create New Post”mutation CreateBlogPost($data: CreateBlogPostInput!) { createBlogPost(data: $data) { id title slug status createdAt }}
Variables:
{ "data": { "title": "My New Blog Post", "content": "<p>This is the content</p>", "status": "PUBLISHED", "authorId": "1" }}
Using with Different Clients
Section titled “Using with Different Clients”// Using fetchconst response = await fetch('https://your-domain.com/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer your-api-key', }, body: JSON.stringify({ query: ` query GetBlogPosts { blogPosts(limit: 5) { nodes { id title publishedAt } } } `, }),});
const data = await response.json();console.log(data.data.blogPosts.nodes);
import requests
url = 'https://your-domain.com/graphql'headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer your-api-key',}
query = """query GetBlogPosts { blogPosts(limit: 5) { nodes { id title publishedAt } }}"""
response = requests.post(url, json={'query': query}, headers=headers)data = response.json()print(data['data']['blogPosts']['nodes'])
<?php$url = 'https://your-domain.com/graphql';$headers = [ 'Content-Type: application/json', 'Authorization: Bearer your-api-key',];
$query = 'query GetBlogPosts { blogPosts(limit: 5) { nodes { id title publishedAt } }}';
$data = json_encode(['query' => $query]);
$curl = curl_init();curl_setopt($curl, CURLOPT_URL, $url);curl_setopt($curl, CURLOPT_POST, true);curl_setopt($curl, CURLOPT_POSTFIELDS, $data);curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);curl_close($curl);
$result = json_decode($response, true);print_r($result['data']['blogPosts']['nodes']);?>
package main
import ( "bytes" "encoding/json" "fmt" "net/http")
type GraphQLRequest struct { Query string `json:"query"`}
func main() { url := "https://your-domain.com/graphql"
query := ` query GetBlogPosts { blogPosts(limit: 5) { nodes { id title publishedAt } } } `
reqBody := GraphQLRequest{Query: query} jsonData, _ := json.Marshal(reqBody)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer your-api-key")
client := &http.Client{} resp, _ := client.Do(req) defer resp.Body.Close()
var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(result["data"])}
File Upload API
Section titled “File Upload API”Handle file uploads for images, documents, and other media.
Upload Single File
Section titled “Upload Single File”POST /api/upload
Form Data:
file
: The file to uploadalt
: Alternative text (for images)folder
: Folder path (optional)
Example:
curl -X POST "https://your-domain.com/api/upload" \ -H "Authorization: Bearer your-api-key" \ -F "file=@image.jpg" \ -F "alt=Sample image" \ -F "folder=blog/images"
Response:
{ "data": { "id": "file_123", "filename": "image.jpg", "originalName": "my-image.jpg", "mimeType": "image/jpeg", "size": 2048576, "url": "https://your-domain.com/uploads/image.jpg", "alt": "Sample image", "folder": "blog/images", "createdAt": "2024-01-15T10:00:00Z" }}
Upload Multiple Files
Section titled “Upload Multiple Files”POST /api/upload/multiple
Example:
curl -X POST "https://your-domain.com/api/upload/multiple" \ -H "Authorization: Bearer your-api-key" \ -F "files[]=@image1.jpg" \ -F "files[]=@image2.jpg"
Webhooks
Section titled “Webhooks”Set up webhooks to receive real-time notifications when content changes.
Configuration
Section titled “Configuration”export default defineConfig({ webhooks: { enabled: true, endpoints: [ { url: 'https://your-app.com/webhook', events: ['create', 'update', 'delete'], models: ['blogPost', 'page'], secret: 'webhook-secret', }, ], },});
Webhook Payload
Section titled “Webhook Payload”{ "event": "create", "model": "blogPost", "data": { "id": "1", "title": "New Blog Post", "status": "published", "createdAt": "2024-01-15T10:00:00Z" }, "timestamp": "2024-01-15T10:00:00Z", "signature": "sha256=..."}
Verifying Webhooks
Section titled “Verifying Webhooks”const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) { const expectedSignature = crypto .createHmac('sha256', secret) .update(payload) .digest('hex');
return `sha256=${expectedSignature}` === signature;}
Rate Limiting
Section titled “Rate Limiting”API requests are rate-limited to prevent abuse:
- Default: 100 requests per 15 minutes per IP
- Authenticated: 1000 requests per 15 minutes per API key
Rate limit headers are included in responses:
X-RateLimit-Limit: 100X-RateLimit-Remaining: 95X-RateLimit-Reset: 1642252800
Error Handling
Section titled “Error Handling”Error Response Format
Section titled “Error Response Format”{ "error": { "code": "VALIDATION_ERROR", "message": "Validation failed", "details": [ { "field": "title", "message": "Title is required" } ] }}
Common Error Codes
Section titled “Common Error Codes”Code | Status | Description |
---|---|---|
UNAUTHORIZED | 401 | Invalid or missing authentication |
FORBIDDEN | 403 | Insufficient permissions |
NOT_FOUND | 404 | Resource not found |
VALIDATION_ERROR | 422 | Request validation failed |
RATE_LIMITED | 429 | Too many requests |
INTERNAL_ERROR | 500 | Server error |