API Reference
SonicJS provides a comprehensive REST API for managing content, collections, media, and authentication programmatically. Built on Cloudflare Workers with a three-tiered caching system for optimal performance.
Introduction
Base URL
https://your-domain.com/api
For local development:
http://localhost:8787/api
Interactive API Documentation
SonicJS includes an interactive API explorer powered by Scalar UI. Access it at:
http://localhost:8787/docs
OpenAPI Specification
Get the complete OpenAPI 3.0 specification:
curl -X GET "http://localhost:8787/api/"
CORS
SonicJS includes built-in CORS (Cross-Origin Resource Sharing) support, allowing you to call the API from frontend applications running on different domainsβsuch as a Next.js, React, or Vue app on localhost:3000.
Default Configuration
CORS is enabled by default with a permissive configuration:
| Setting | Value |
|---|---|
| Allowed Origins | * (all origins) |
| Allowed Methods | GET, POST, PUT, DELETE, OPTIONS |
| Allowed Headers | Content-Type, Authorization |
This means your frontend application can immediately start making API requests without any additional configuration.
How It Works
SonicJS uses Hono's CORS middleware applied to all API routes:
import { cors } from 'hono/cors'
apiRoutes.use('*', cors({
origin: '*',
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization']
}))
Preflight Requests
For requests that require preflight checks (e.g., POST with JSON body), the browser sends an OPTIONS request first. SonicJS automatically handles these and returns a 204 No Content response with the appropriate CORS headers.
Example: Fetching from Next.js
Next.js API Call
// app/components/Posts.tsx
'use client'
import { useEffect, useState } from 'react'
export default function Posts() {
const [posts, setPosts] = useState([])
useEffect(() => {
fetch('http://localhost:8787/api/collections/blog-posts/content')
.then(res => res.json())
.then(data => setPosts(data.data))
}, [])
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
Media Files
Static files served from R2 storage (/files/*) also include CORS headers:
| Setting | Value |
|---|---|
| Allowed Origins | * (all origins) |
| Allowed Methods | GET, HEAD, OPTIONS |
| Allowed Headers | Content-Type |
This allows you to load images and other media directly in your frontend application.
Custom CORS Configuration
The default CORS configuration is hardcoded for maximum accessibility. If you need to restrict origins for production, you can modify the CORS middleware in packages/core/src/routes/api.ts:
// Example: Restrict to specific origins
apiRoutes.use('*', cors({
origin: ['https://your-app.com', 'https://admin.your-app.com'],
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization'],
credentials: true // Enable if using cookies
}))
Authentication
Most API endpoints require authentication. SonicJS uses JWT (JSON Web Tokens) with HTTP-only cookies for web clients and Bearer tokens for API clients.
Login
Get an access token by authenticating with your credentials.
Login Request
curl -X POST "http://localhost:8787/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "admin@sonicjs.com",
"password": "sonicjs!"
}'
Login Response
200 Success
{
"user": {
"id": "admin-user-id",
"email": "admin@sonicjs.com",
"username": "admin",
"firstName": "Admin",
"lastName": "User",
"role": "admin"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
401 Error
{
"error": "Invalid email or password"
}
Using the Token
Include the token in the Authorization header for all authenticated requests:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
For browser-based applications, the token is automatically stored as an HTTP-only cookie named auth_token.
Register
Create a new user account.
Register Request
curl -X POST "http://localhost:8787/auth/register" \
-H "Content-Type: application/json" \
-d '{
"email": "newuser@example.com",
"password": "securepassword123",
"username": "newuser",
"firstName": "John",
"lastName": "Doe"
}'
Get Current User
Get information about the currently authenticated user.
Get User Request
curl -X GET "http://localhost:8787/auth/me" \
-H "Authorization: Bearer {token}"
Refresh Token
Refresh your access token before it expires.
curl -X POST "http://localhost:8787/auth/refresh" \
-H "Authorization: Bearer {token}"
Logout
End your session.
curl -X POST "http://localhost:8787/auth/logout"
Collections
List All Collections
Retrieve all active collections with their schemas.
Authentication: None required Cache: 5 minutes
List Collections
curl -X GET "http://localhost:8787/api/collections"
Collections Response
200 Success
{
"data": [
{
"id": "blog-posts-collection-id",
"name": "blog-posts",
"display_name": "Blog Posts",
"description": "Blog posts collection",
"schema": {
"name": "blog-posts",
"displayName": "Blog Posts",
"fields": [
{
"name": "title",
"type": "text",
"label": "Title",
"required": true
},
{
"name": "content",
"type": "richtext",
"label": "Content"
},
{
"name": "featuredImage",
"type": "media",
"label": "Featured Image"
}
]
},
"is_active": 1,
"created_at": 1730000000,
"updated_at": 1730000000
}
],
"meta": {
"count": 1,
"timestamp": "2025-10-06T12:34:56.789Z",
"cache": {
"hit": false,
"source": "database"
},
"timing": {
"total": 45,
"execution": 12,
"unit": "ms"
}
}
}
Content Management
List All Content
Retrieve all content items with pagination and filtering.
Authentication: None required Cache: 5 minutes
Query Parameters:
limit- Maximum items to return (default: 50, max: 100)offset- Number of items to skip for paginationsort- Sort field (prefix with-for descending)filter- Advanced filtering (see Filtering & Querying)
List Content
curl -X GET "http://localhost:8787/api/content?limit=10"
Get Content by Collection
Retrieve content for a specific collection.
Authentication: None required Cache: 5 minutes
Get Collection Content
curl -X GET "http://localhost:8787/api/collections/blog-posts/content?limit=25"
Get Single Content Item
Retrieve a specific content item by ID.
Authentication: None required Cache: 5 minutes
Get Content
curl -X GET "http://localhost:8787/api/content/{id}"
Create Content
Create a new content item.
Authentication: Required Permissions: Editor or Admin role
Create Content
curl -X POST "http://localhost:8787/api/content" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"collectionId": "blog-posts-collection-id",
"title": "My New Blog Post",
"slug": "my-new-blog-post",
"status": "draft",
"data": {
"title": "My New Blog Post",
"content": "<p>This is my blog post content...</p>",
"excerpt": "A brief description"
}
}'
Update Content
Update an existing content item.
Authentication: Required Permissions: Content owner, Editor, or Admin role
Update Content
curl -X PUT "http://localhost:8787/api/content/{id}" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"title": "Updated Blog Post Title",
"status": "published",
"data": {
"title": "Updated Blog Post Title",
"content": "<p>Updated content...</p>"
}
}'
Delete Content
Delete a content item.
Authentication: Required Permissions: Content owner, Editor, or Admin role
Delete Content
curl -X DELETE "http://localhost:8787/api/content/{id}" \
-H "Authorization: Bearer {token}"
Media Management
All media endpoints require authentication.
Upload Single File
Upload a file to Cloudflare R2 storage.
Authentication: Required
Content-Type: multipart/form-data
Max File Size: 50MB
Supported File Types:
- Images: JPEG, PNG, GIF, WebP, SVG
- Documents: PDF, TXT, DOC, DOCX
- Videos: MP4, WebM, OGG, AVI, MOV
- Audio: MP3, WAV, OGG, M4A
Upload File
curl -X POST "http://localhost:8787/api/media/upload" \
-H "Authorization: Bearer {token}" \
-F "file=@/path/to/image.jpg" \
-F "folder=blog-images"
Upload Response
200 Success
{
"success": true,
"file": {
"id": "V1StGXR8_Z5jdHi6B",
"filename": "V1StGXR8_Z5jdHi6B.jpg",
"originalName": "my-image.jpg",
"mimeType": "image/jpeg",
"size": 245678,
"width": 1920,
"height": 1080,
"publicUrl": "https://pub-sonicjs-media-dev.r2.dev/blog-images/V1StGXR8_Z5jdHi6B.jpg",
"thumbnailUrl": "https://imagedelivery.net/account-id/blog-images/V1StGXR8_Z5jdHi6B.jpg/thumbnail",
"uploadedAt": "2025-10-06T12:34:56.789Z"
}
}
400 Error
{
"error": "File validation failed",
"details": [
{
"code": "too_big",
"message": "File size exceeds 50MB limit",
"path": ["size"]
}
]
}
Upload Multiple Files
Upload multiple files in a single request.
Authentication: Required
Upload Multiple Files
curl -X POST "http://localhost:8787/api/media/upload-multiple" \
-H "Authorization: Bearer {token}" \
-F "files=@/path/to/image1.jpg" \
-F "files=@/path/to/image2.png" \
-F "folder=gallery"
Update File Metadata
Update file metadata (alt text, caption, tags, folder).
Authentication: Required Permissions: Uploader or Admin role
Update File
curl -X PATCH "http://localhost:8787/api/media/{id}" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"alt": "Beautiful sunset over the ocean",
"caption": "Sunset at Malibu Beach",
"tags": ["nature", "sunset", "ocean"],
"folder": "featured-images"
}'
Delete File
Delete a single file.
Authentication: Required Permissions: Uploader or Admin role
Delete File
curl -X DELETE "http://localhost:8787/api/media/{id}" \
-H "Authorization: Bearer {token}"
Bulk Delete Files
Delete multiple files in a single request.
Authentication: Required Max Files: 50 per request
Bulk Delete
curl -X POST "http://localhost:8787/api/media/bulk-delete" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"fileIds": ["file-id-1", "file-id-2", "file-id-3"]
}'
Bulk Move Files
Move multiple files to a different folder.
Authentication: Required Max Files: 50 per request
Bulk Move
curl -X POST "http://localhost:8787/api/media/bulk-move" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"fileIds": ["file-id-1", "file-id-2"],
"targetFolder": "archived"
}'
System Endpoints
Health Check
Check API and system health.
Authentication: None required
Health Check
curl -X GET "http://localhost:8787/api/health"
System Information
Get system information and available features.
Authentication: None required
curl -X GET "http://localhost:8787/api/system/info"
System Statistics
Get database statistics (content count, media count, user count).
Authentication: Admin role required
curl -X GET "http://localhost:8787/api/system/stats" \
-H "Authorization: Bearer {token}"
Database Ping
Check database connectivity and latency.
Authentication: None required
curl -X GET "http://localhost:8787/api/system/ping"
Filtering & Querying
SonicJS provides powerful filtering capabilities for content queries.
Filter Operators
| Operator | Description | Example |
|---|---|---|
equals | Exact match | filter[status][equals]=published |
not_equals | Not equal | filter[status][not_equals]=draft |
greater_than | Greater than | filter[price][greater_than]=100 |
less_than | Less than | filter[price][less_than]=1000 |
like | Case-insensitive search | filter[title][like]=javascript |
contains | String contains | filter[tags][contains]=tutorial |
in | Value in list | filter[category][in]=blog,news |
not_in | Value not in list | filter[status][not_in]=draft,archived |
exists | Field exists | filter[featuredImage][exists]=true |
Filter Examples
Simple equality filter:
curl "http://localhost:8787/api/content?filter[status][equals]=published"
Multiple filters (AND logic):
curl "http://localhost:8787/api/content?\
filter[status][equals]=published&\
filter[category][equals]=blog&\
filter[price][less_than]=100"
Search with LIKE:
curl "http://localhost:8787/api/content?filter[title][like]=getting started"
Filter with IN operator:
curl "http://localhost:8787/api/content?filter[category][in]=blog,tutorial,guide"
Date range filter:
curl "http://localhost:8787/api/content?\
filter[created_at][greater_than]=2025-01-01&\
filter[created_at][less_than]=2025-12-31"
Sorting
Sort results by any field. Prefix with - for descending order.
# Sort by created_at descending
curl "http://localhost:8787/api/content?sort=-created_at"
# Sort by title ascending
curl "http://localhost:8787/api/content?sort=title"
Pagination
Use limit and offset for pagination.
# Get first 10 items
curl "http://localhost:8787/api/content?limit=10&offset=0"
# Get next 10 items
curl "http://localhost:8787/api/content?limit=10&offset=10"
Caching
SonicJS implements a three-tiered caching system for optimal performance.
Cache Tiers
- Memory Cache - In-memory cache (fastest, ~1-3ms)
- KV Cache - Cloudflare KV storage (fast, ~5-15ms)
- Database - D1 database (slower, ~20-50ms)
Cache Headers
Every API response includes cache information:
X-Cache-Status: HIT
X-Cache-Source: memory
X-Cache-TTL: 278
X-Response-Time: 3ms
Headers:
X-Cache-Status-HITorMISSX-Cache-Source-memory,kv, ordatabaseX-Cache-TTL- Remaining TTL in seconds (cache hits only)X-Response-Time- Total response time
Cache TTLs
| Resource | TTL | Memory | KV |
|---|---|---|---|
| API responses | 5 min | β | β |
| Collections | 2 hours | β | β |
| Content | 1 hour | β | β |
| User data | 15 min | β | β |
| Media metadata | 1 hour | β | β |
Cache Invalidation
Caches are automatically invalidated when:
- Content is created, updated, or deleted
- Collections are modified
- Media files are uploaded or deleted
- User permissions change
Error Handling
SonicJS uses standard HTTP status codes and returns consistent error responses.
HTTP Status Codes
| Code | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 500 | Internal Server Error |
Error Response Format
{
"error": "Error message",
"details": [
{
"code": "validation_error",
"message": "Field is required",
"path": ["fieldName"]
}
]
}
Common Errors
401 Unauthorized:
{
"error": "Authentication required"
}
403 Forbidden:
{
"error": "Insufficient permissions"
}
404 Not Found:
{
"error": "Resource not found"
}
400 Validation Error:
{
"error": "Validation failed",
"details": [
{
"code": "invalid_type",
"message": "Expected string, received number",
"path": ["title"]
}
]
}
Rate Limiting
Currently, SonicJS does not enforce rate limits. This may change in future versions.
For production deployments, consider implementing rate limiting at the Cloudflare Workers level using:
- Cloudflare Rate Limiting
- Custom middleware using Cloudflare KV
Next Steps
- Authentication Guide - Deep dive into authentication and RBAC
- Collections - Learn about collection schemas and field types
- Caching - Understand the caching system in detail
- Testing - Write tests for your API integrations
For questions or support, visit our Community page.