JSON-RPC Style API
JSON-RPC Style API
The primary ObjectQL API is a JSON-RPC style protocol where all operations are sent to a single endpoint.
Base Endpoint
POST /api/objectql
Content-Type: application/jsonRequest Format
interface ObjectQLRequest {
// Authentication context (optional, can also come from headers)
user?: {
id: string;
roles: string[];
[key: string]: any;
};
// The operation to perform
op: 'find' | 'findOne' | 'create' | 'update' | 'delete' | 'count' | 'action' | 'createMany' | 'updateMany' | 'deleteMany';
// The target object/table
object: string;
// Operation-specific arguments
args: any;
}Response Format
interface ObjectQLResponse {
// For list operations (find)
items?: any[];
// Pagination metadata (for list operations)
meta?: {
total: number; // Total number of records
page?: number; // Current page number (1-indexed)
size?: number; // Number of items per page
pages?: number; // Total number of pages
has_next?: boolean; // Whether there is a next page
};
// For single item operations, the response is the object itself with '@type' field
// Examples: findOne, create, update return { id: '...', name: '...', '@type': 'users' }
'@type'?: string; // Object type identifier
// Error information
error?: {
code: string;
message: string;
details?: any;
};
// Other fields from the actual data object (for single item responses)
[key: string]: any;
}Operations
1. find - Query Records
Retrieve multiple records with filtering, sorting, pagination, and joins.
Request:
{
"op": "find",
"object": "orders",
"args": {
"fields": ["order_no", "amount", "status", "created_at"],
"filters": [
["status", "=", "paid"],
"and",
["amount", ">", 1000]
],
"sort": [["created_at", "desc"]],
"top": 20,
"skip": 0,
"expand": {
"customer": {
"fields": ["name", "email"]
}
}
}
}Response:
{
"items": [
{
"order_no": "ORD-001",
"amount": 1500,
"status": "paid",
"created_at": "2024-01-15T10:30:00Z",
"customer": {
"name": "Acme Corp",
"email": "contact@acme.com"
}
}
],
"meta": {
"total": 150,
"page": 1,
"size": 20,
"pages": 8,
"has_next": true
}
}2. findOne - Get Single Record
Retrieve a single record by ID or query.
Request (by ID):
{
"op": "findOne",
"object": "users",
"args": "user_123"
}Request (by query):
{
"op": "findOne",
"object": "users",
"args": {
"filters": [["email", "=", "alice@example.com"]]
}
}Response:
{
"id": "user_123",
"name": "Alice",
"email": "alice@example.com",
"@type": "users"
}3. create - Create Record
Insert a new record.
Request:
{
"op": "create",
"object": "tasks",
"args": {
"name": "Review PR",
"priority": "high",
"assignee_id": "user_123",
"due_date": "2024-01-20"
}
}Response:
{
"id": "task_456",
"name": "Review PR",
"priority": "high",
"assignee_id": "user_123",
"due_date": "2024-01-20",
"created_at": "2024-01-15T10:30:00Z",
"@type": "tasks"
}4. update - Update Record
Modify an existing record.
Request:
{
"op": "update",
"object": "tasks",
"args": {
"id": "task_456",
"data": {
"status": "completed",
"completed_at": "2024-01-16T14:00:00Z"
}
}
}Response:
{
"id": "task_456",
"status": "completed",
"completed_at": "2024-01-16T14:00:00Z",
"@type": "tasks"
}5. delete - Delete Record
Remove a record by ID.
Request:
{
"op": "delete",
"object": "tasks",
"args": {
"id": "task_456"
}
}Response:
{
"id": "task_456",
"deleted": true,
"@type": "tasks"
}6. count - Count Records
Get the count of records matching a filter.
Request:
{
"op": "count",
"object": "orders",
"args": {
"filters": [
["status", "=", "pending"]
]
}
}Response:
{
"count": 42,
"@type": "orders"
}7. action - Execute Custom Action
Execute a custom server-side action (RPC-style operation).
Request:
{
"op": "action",
"object": "orders",
"args": {
"action": "approve",
"id": "order_789",
"input": {
"approved_by": "manager_123",
"notes": "Approved for expedited shipping"
}
}
}Response:
{
"success": true,
"message": "Order approved successfully",
"order": {
"id": "order_789",
"status": "approved",
"approved_at": "2024-01-15T10:30:00Z"
},
"@type": "orders"
}Bulk Operations
ObjectQL supports efficient bulk operations for creating, updating, and deleting multiple records in a single request.
Important Notes:
- Validation & Hooks: Bulk operations process each record individually to ensure validation rules and hooks (beforeCreate, afterCreate, etc.) are properly executed, maintaining data integrity
- Atomicity: Operations are not atomic by default - if one record fails, others may have already been processed
- Performance: While bulk operations are more efficient than separate API calls, they may be slower than driver-level bulk operations due to individual validation/hook execution
- Use Cases: Use bulk operations when you need consistent validation and business logic enforcement. For high-performance batch imports where validation is already handled, consider using driver-level operations directly
8. createMany - Create Multiple Records
Insert multiple records in a single operation.
Request:
{
"op": "createMany",
"object": "tasks",
"args": [
{
"name": "Task 1",
"priority": "high",
"assignee_id": "user_123"
},
{
"name": "Task 2",
"priority": "medium",
"assignee_id": "user_456"
},
{
"name": "Task 3",
"priority": "low",
"assignee_id": "user_789"
}
]
}Response:
{
"items": [
{
"id": "task_101",
"name": "Task 1",
"priority": "high",
"assignee_id": "user_123",
"created_at": "2024-01-15T10:30:00Z"
},
{
"id": "task_102",
"name": "Task 2",
"priority": "medium",
"assignee_id": "user_456",
"created_at": "2024-01-15T10:30:00Z"
},
{
"id": "task_103",
"name": "Task 3",
"priority": "low",
"assignee_id": "user_789",
"created_at": "2024-01-15T10:30:00Z"
}
],
"count": 3,
"@type": "tasks"
}9. updateMany - Update Multiple Records
Update all records matching a filter.
Request:
{
"op": "updateMany",
"object": "tasks",
"args": {
"filters": {
"status": "pending",
"priority": "low"
},
"data": {
"status": "cancelled",
"cancelled_at": "2024-01-15T10:30:00Z"
}
}
}Response:
{
"count": 15,
"@type": "tasks"
}10. deleteMany - Delete Multiple Records
Delete all records matching a filter.
Request:
{
"op": "deleteMany",
"object": "tasks",
"args": {
"filters": {
"status": "completed",
"completed_at": ["<", "2023-01-01"]
}
}
}Response:
{
"count": 42,
"@type": "tasks"
}Error Handling Example:
// If a record fails validation during bulk operation
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {
"fields": {
"priority": "Invalid priority value"
}
}
}
}Advanced Query Features
AI Context (Optional)
Add semantic information to queries for better logging, debugging, and AI processing:
{
"op": "find",
"object": "projects",
"ai_context": {
"intent": "Find at-risk projects requiring immediate attention",
"natural_language": "Show active projects that are overdue or over budget",
"use_case": "Project manager dashboard"
},
"args": {
"filters": [
["status", "=", "active"],
"and",
[
["end_date", "<", "$today"],
"or",
["actual_cost", ">", "budget"]
]
]
}
}Aggregation Queries
Perform GROUP BY operations:
{
"op": "find",
"object": "orders",
"args": {
"groupBy": ["category"],
"aggregate": [
{
"func": "sum",
"field": "amount",
"alias": "total_sales"
},
{
"func": "count",
"field": "id",
"alias": "order_count"
}
],
"filters": [["status", "=", "paid"]],
"sort": [["total_sales", "desc"]]
}
}