MantisBase provides auto-generated RESTful APIs for interacting with database entities. This document covers the entity endpoints, schema management, realtime (SSE) API for live database change notifications (SQLite and PostgreSQL), and request handling.
🌐 Base URL
When MantisBase is running locally:
http://localhost:7070/api/v1/
You can configure the port and host using command-line arguments:
mantisbase serve -p 8000 -h 127.0.0.1
📄 Entity Endpoints
MantisBase automatically exposes CRUD endpoints for each entity (table or view):
| Method | Endpoint | Description |
| GET | /api/v1/entities/<entity> | List all records |
| GET | /api/v1/entities/<entity>/:id | Get a specific record |
| POST | /api/v1/entities/<entity> | Create a new record |
| PATCH | /api/v1/entities/<entity>/:id | Update partial fields |
| DELETE | /api/v1/entities/<entity>/:id | Delete a record |
Example Requests
# List all users
curl http://localhost:7070/api/v1/entities/users
# Get specific user
curl http://localhost:7070/api/v1/entities/users/123
# Create a new user
curl -X POST http://localhost:7070/api/v1/entities/users \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"name": "John Doe", "email": "john@example.com"}'
# Update user
curl -X PATCH http://localhost:7070/api/v1/entities/users/123 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"name": "Jane Doe"}'
# Delete user
curl -X DELETE http://localhost:7070/api/v1/entities/users/123 \
-H "Authorization: Bearer <token>"
🔐 Authentication
All entity endpoints require authentication via JWT tokens. Include the token in the Authorization header:
Authorization: Bearer <token>
For authentication endpoints, see Authentication API.
🛡️ Middlewares
Middlewares are functions that run before your route handler, allowing you to add authentication, authorization, and request processing logic.
Default Middlewares
Every endpoint automatically has two middlewares applied globally:
- **
getAuthToken()** - Extracts JWT token from Authorization header and stores it in request context
- **
hydrateContextData()** - Validates token, fetches user data from database, and populates request context with user information
Additionally, entity endpoints automatically have:
- **
hasAccess(entity_name)** - Evaluates entity access rules to determine if the authenticated user can perform the requested operation. Called automatically by entity endpoints to confirm access rules before data query.
Available Middlewares
You can use these middlewares when creating custom endpoints:
| Middleware | Description | Usage |
getAuthToken() | Extract token from Authorization header | Applied globally to all routes |
hydrateContextData() | Validate token and load user data | Applied globally to all routes |
hasAccess(entity_name) | Check entity access rules | Applied automatically to entity endpoints |
requireAdminAuth() | Require admin authentication | Blocks non-admin users |
requireEntityAuth(entity_name) | Require authentication from specific entity | Only allows users from specified entity table |
requireAdminOrEntityAuth(entity_name) | Require admin OR entity auth | Allows admins or users from specified entity |
requireGuestOnly() | Require no authentication | Blocks authenticated users, only allows guests |
requireExprEval(expr) | Evaluate custom expression | Custom expression-based access control |
rateLimit(max_requests, window_seconds, use_user_id) | Rate limiting middleware | Limits requests per time window by IP or user ID |
Using Middlewares
When creating custom endpoints, you can specify middlewares as the third parameter:
router.Get("/api/v1/admin/stats", [](MantisRequest& req, MantisResponse& res) {
res.sendJSON(200, {{"stats", "data"}});
router.Get("/api/v1/users/profile", [](MantisRequest& req, MantisResponse& res) {
auto auth = req.getOr<
json>(
"auth", json::object());
std::string userId = auth["id"];
router.Get("/api/v1/posts/draft", [](MantisRequest& req, MantisResponse& res) {
router.Get("/api/v1/public/info", [](MantisRequest& req, MantisResponse& res) {
res.sendJSON(200, {{"info", "public data"}});
router.Get("/api/v1/restricted", [](MantisRequest& req, MantisResponse& res) {
router.Get("/api/v1/data", [](MantisRequest& req, MantisResponse& res) {
res.sendJSON(200, {{"data", "response"}});
router.Post("/api/v1/upload", [](MantisRequest& req, MantisResponse& res) {
router.Post("/api/v1/sensitive", [](MantisRequest& req, MantisResponse& res) {
}, {
});
std::function< HandlerResponse(MantisRequest &, MantisResponse &)> rateLimit(int max_requests, int window_seconds, bool use_user_id=false)
Rate limiting middleware to prevent abuse.
Definition middlewares.cpp:404
std::function< HandlerResponse(MantisRequest &, MantisResponse &)> requireAdminOrEntityAuth(const std::string &entity_name)
Require admin OR entity authentication.
Definition middlewares.cpp:371
std::function< HandlerResponse(MantisRequest &, MantisResponse &)> requireGuestOnly()
Require guest-only access (no authentication).
Definition middlewares.cpp:282
std::function< HandlerResponse(MantisRequest &, MantisResponse &)> requireExprEval(const std::string &expr)
Require expression evaluation to pass.
Definition middlewares.cpp:274
std::function< HandlerResponse(MantisRequest &, MantisResponse &)> requireAdminAuth()
Require admin authentication.
Definition middlewares.cpp:299
std::function< HandlerResponse(MantisRequest &, MantisResponse &)> requireEntityAuth(const std::string &entity_name)
Require entity-specific authentication.
Definition middlewares.cpp:381
nlohmann::json json
Shorten JSON namespace.
Definition context_store.h:18
Accessing User Data in Handlers
After middlewares run, you can access authenticated user data from the request context:
router.Get("/api/v1/me", [](MantisRequest& req, MantisResponse& res) {
auto auth = req.getOr<json>("auth", json::object());
if (auth["type"] == "guest") {
res.sendJSON(401, {{"error", "Not authenticated"}});
return;
}
std::string userId = auth["id"];
std::string userEntity = auth["entity"];
json userData = auth[
"user"];
res.sendJSON(200, {{"user", userData}});
});
Note: Middlewares execute in the order they are specified. If a middleware returns HandlerResponse::Handled, subsequent middlewares and the handler are skipped.
</blockquote>
🗃️ Schema Management API
Schema management endpoints allow you to create, read, update, and delete entity schemas. These endpoints require admin authentication only.
| Method | Endpoint | Description |
| GET | /api/v1/schemas | List all schemas |
| GET | /api/v1/schemas/:schema_name_or_id | Get a specific schema |
| POST | /api/v1/schemas | Create a new schema |
| PATCH | /api/v1/schemas/:schema_name_or_id | Update a schema |
| DELETE | /api/v1/schemas/:schema_name_or_id | Delete a schema |
Example: Create a Schema
Base Entity (Standard Table):
curl -X POST http://localhost:7070/api/v1/schemas \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "posts",
"type": "base",
"fields": [
{"name": "title", "type": "string", "required": true},
{"name": "content", "type": "string"},
{"name": "author_id", "type": "string", "required": true}
],
"rules": {
"list": {"mode": "public", "expr": "auth.id != \"\""},
"get": {"mode": "auth", "expr": ""},
"add": {"mode": "auth", "expr": ""},
"update": {"mode": "auth", "expr": ""},
"delete": {"mode": "custom", "expr": "auth.entity == \"mb_admins\""}
}
}'
View Entity (SQL View):
curl -X POST http://localhost:7070/api/v1/schemas \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "published_posts",
"type": "view",
"view_query": "SELECT * FROM posts WHERE status = '\''published'\''",
"rules": {
"list": {"mode": "public", "expr": ""},
"get": {"mode": "public", "expr": ""}
}
}'
Auth Entity (Authentication Table):
curl -X POST http://localhost:7070/api/v1/schemas \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "users",
"type": "auth",
"fields": [
{"name": "email", "type": "string", "required": true, "is_unique": true},
{"name": "full_name", "type": "string"}
],
"rules": {
"list": {"mode": "auth", "expr": ""},
"get": {"mode": "auth", "expr": ""},
"add": {"mode": "public", "expr": ""},
"update": {"mode": "custom", "expr": "auth.id == req.body.id"},
"delete": {"mode": "", "expr": ""}
}
}'
Entity Types
MantisBase supports three entity types:
| Type | Description | Fields | Special Properties |
base | Standard database table | Yes | Standard CRUD operations |
auth | Authentication entity | Yes | Includes password, email, and user management fields automatically |
view | SQL view (read-only) | No | Requires view_query instead of fields |
Entity Name Validation
Entity names must follow these rules:
- Alphanumeric and underscores only - Only letters, numbers, and
_ characters allowed
- Maximum 64 characters - Names cannot exceed 64 characters
- Not empty - Names must contain at least one character
Invalid names will be rejected with a 400 error.
Updating Schemas
When updating a schema, you can add, update, or remove fields:
curl -X PATCH http://localhost:7070/api/v1/schemas/posts \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"fields": [
{"name": "new_field", "type": "string"}, // Add new field
{"id": "field_id_123", "type": "text"}, // Update existing field by ID
{"id": "old_field_id", "op": "delete"} // Remove field
]
}'
Field Operations:
- Add: Include a field with a
name that doesn't exist
- Update: Include a field with an existing
id
- Delete: Include a field with an existing
id and "op": "delete" or "op": "remove"
⚠️ Admin Only: All schema endpoints require admin authentication. Regular users cannot access these endpoints.
</blockquote>
🎛️ Query Parameters [PENDING]
Future support for filtering, sorting, and pagination:
GET /api/v1/entities/tasks?status=done&limit=10&offset=20&sort=-created_at
⚙️ Custom Endpoints
You can create custom API endpoints using the router:
router.Get("/api/v1/custom", [](MantisRequest& req, MantisResponse& res) {
res.sendJSON(200, {{"message", "Custom endpoint"}});
Check the Embedding Guide for more details.
📁 File Handling
Files uploaded via multipart/form-data are stored and can be accessed at:
GET /api/files/<entity>/<filename>
See File Handling for more details.
🔍 Entity Types and Validation
Entity Types
MantisBase supports three types of entities:
Base Entities
Standard database tables with fields. Use for most data storage needs.
{
"name": "posts",
"type": "base",
"fields": [
{"name": "title", "type": "string", "required": true},
{"name": "content", "type": "string"}
]
}
Auth Entities
Authentication entities with built-in password and user management fields. Automatically includes:
password - Hashed password field
email - Email field (typically unique)
- Standard user management fields
{
"name": "users",
"type": "auth",
"fields": [
{"name": "email", "type": "string", "required": true, "is_unique": true},
{"name": "full_name", "type": "string"}
]
}
View Entities
SQL views based on queries. Read-only, no fields defined. Use view_query instead of fields.
{
"name": "published_posts",
"type": "view",
"view_query": "SELECT * FROM posts WHERE status = 'published'"
}
Entity Name Validation
All entity names are automatically validated to prevent SQL injection and ensure consistency:
Validation Rules:
- ✅ Alphanumeric characters and underscores only (
a-z, A-Z, 0-9, _)
- ✅ Maximum 64 characters
- ✅ Not empty
Invalid Examples:
my-table (contains hyphen)
my table (contains space)
my@table (contains special character)
- Names longer than 64 characters
Invalid names will result in a 400 Bad Request error with a descriptive message.
Foreign Key Relationships
Foreign keys allow you to establish relationships between entities. When creating or updating schemas with foreign key fields, MantisBase automatically validates the relationships.
Foreign Key Structure
Foreign keys are defined using a foreign_key object in the field definition:
{
"name": "post_id",
"type": "string",
"foreign_key": {
"entity": "posts",
"field": "id",
"on_update": "CASCADE",
"on_delete": "CASCADE"
}
}
Foreign Key Properties
| Property | Type | Required | Default | Description |
entity | string | Yes | - | Name of the referenced entity (table) |
field | string | No | "id" | Column name in the referenced entity |
on_update | string | No | "RESTRICT" | Action when referenced record is updated |
on_delete | string | No | "RESTRICT" | Action when referenced record is deleted |
Foreign Key Policies
Both on_update and on_delete support the following policies:
| Policy | Description |
CASCADE | Automatically update/delete related records |
SET NULL | Set foreign key field to NULL when referenced record is updated/deleted |
RESTRICT | Prevent update/delete if related records exist (default) |
NO ACTION | Similar to RESTRICT, but checked after the operation |
SET DEFAULT | Set foreign key field to its default value |
Foreign Key Validation
When creating or updating schemas with foreign keys, MantisBase automatically validates:
- Referenced Entity Exists - The entity referenced by
foreign_key.entity must exist
- Referenced Field Exists - The field specified in
foreign_key.field must exist in the referenced entity
- Type Compatibility - Field types should be compatible (warnings issued for mismatches)
Note: If the referenced entity doesn't exist yet, a warning is issued but the schema is still created. The database will enforce the constraint when the DDL is executed.
Examples
Example 1: Comments with Post Reference
{
"name": "comments",
"type": "base",
"fields": [
{"name": "content", "type": "string", "required": true},
{
"name": "post_id",
"type": "string",
"required": true,
"foreign_key": {
"entity": "posts",
"field": "id",
"on_delete": "CASCADE"
}
}
]
}
Example 2: User Profile with User Reference
{
"name": "profiles",
"type": "base",
"fields": [
{"name": "bio", "type": "string"},
{
"name": "user_id",
"type": "string",
"required": true,
"foreign_key": {
"entity": "users",
"field": "id",
"on_update": "CASCADE",
"on_delete": "CASCADE"
}
}
]
}
Example 3: Removing a Foreign Key
To remove a foreign key constraint, set foreign_key to null:
PATCH /api/v1/schemas/comments
{
"fields": [
{
"id": "post_id_field_id",
"foreign_key": null
}
]
}
Constraint Naming
Foreign key constraints are automatically named using the pattern: fk_<table_name>_<field_name>
For example, a foreign key on post_id in the comments table would create a constraint named fk_comments_post_id.
📊 System Endpoints
Logs Endpoint
The logs endpoint provides access to system logs with filtering, pagination, and sorting capabilities. Requires admin authentication.
| Method | Endpoint | Description |
| GET | /api/v1/sys/logs | Get system logs with filtering and pagination |
Query Parameters
| Parameter | Type | Default | Description |
page | integer | 1 | Page number (1-based) |
page_size | integer | 50 | Number of records per page (max 1000) |
level | string | - | Filter by exact log level: trace, debug, info, warn, critical |
min_level | string | - | Filter by minimum log level (includes that level and above) |
search | string | - | Search in log messages |
start_date | string | - | Start date filter (ISO 8601 format) |
end_date | string | - | End date filter (ISO 8601 format) |
sort_by | string | "timestamp" | Sort field: level, origin, message, timestamp, created_at |
sort_order | string | "desc" | Sort order: asc or desc |
Example Requests
# Get recent logs (default: page 1, 50 records)
curl -H "Authorization: Bearer <admin_token>" \
http://localhost:7070/api/v1/sys/logs
# Get logs with pagination
curl -H "Authorization: Bearer <admin_token>" \
"http://localhost:7070/api/v1/sys/logs?page=2&page_size=100"
# Filter by log level
curl -H "Authorization: Bearer <admin_token>" \
"http://localhost:7070/api/v1/sys/logs?level=warn"
# Get all errors and warnings (min_level)
curl -H "Authorization: Bearer <admin_token>" \
"http://localhost:7070/api/v1/sys/logs?min_level=warn"
# Search in log messages
curl -H "Authorization: Bearer <admin_token>" \
"http://localhost:7070/api/v1/sys/logs?search=database"
# Filter by date range
curl -H "Authorization: Bearer <admin_token>" \
"http://localhost:7070/api/v1/sys/logs?start_date=2024-01-01T00:00:00Z&end_date=2024-01-31T23:59:59Z"
# Sort by level, ascending
curl -H "Authorization: Bearer <admin_token>" \
"http://localhost:7070/api/v1/sys/logs?sort_by=level&sort_order=asc"
# Combined filters
curl -H "Authorization: Bearer <admin_token>" \
"http://localhost:7070/api/v1/sys/logs?min_level=warn&search=error&page=1&page_size=20&sort_by=timestamp&sort_order=desc"
Response Format
{
"logs": [
{
"id": "log_id_123",
"timestamp": "2024-01-15T10:30:45Z",
"level": "warn",
"origin": "entitySchema",
"message": "Foreign key validation warning",
"details": "Additional details about the log entry",
"data": {},
"created_at": "2024-01-15T10:30:45Z"
}
],
"pagination": {
"page": 1,
"page_size": 50,
"total": 1250,
"total_pages": 25
}
}
Log Levels
Log levels in order of severity (lowest to highest):
trace - Detailed debugging information
debug - General debugging information
info - Informational messages
warn - Warning messages
critical - Critical errors
When using min_level, all logs at that level and above are included. For example, min_level=warn includes warn and critical logs.
Error Responses
503 Service Unavailable - Log database not initialized:
{
"error": "Log database not initialized",
"status": 503,
"data": {}
}
500 Internal Server Error - Server error:
{
"error": "Failed to fetch logs: <error message>",
"status": 500,
"data": {}
}
📡 Realtime API
MantisBase provides realtime database change notifications over Server-Sent Events (SSE) for both SQLite and PostgreSQL backends. Clients subscribe to topics (entity names and optionally specific row IDs) and receive live insert, update, and delete events as they occur.
Endpoints
| Method | Endpoint | Description |
| GET | /api/v1/realtime | Open an SSE connection. Requires topics query parameter. |
| POST | /api/v1/realtime | Update topics for an existing session or clear topics to disconnect. Requires JSON body. |
GET /api/v1/realtime — Open SSE connection
Establishes a long-lived SSE stream. Pass a comma-separated list of topics in the query string.
Query parameters
| Parameter | Type | Required | Description |
topics | string | Yes | Comma-separated list of topics. Each topic is an entity name (e.g. posts) or entity:row_id (e.g. posts:019c1b81-364b-7000-8120-b5416b2c42c2) for a specific row. |
Example
curl -N -H "Authorization: Bearer <token>" \
"http://localhost:7070/api/v1/realtime?topics=posts,users,posts:019c1b81-364b-7000-8120-b5416b2c42c2"
Response
- Content-Type:
text/event-stream
- Connection: keep-alive
The stream sends events in SSE format. Each event has an event type and a data line (JSON).
POST /api/v1/realtime — Update or disconnect session
Updates the list of topics for an existing SSE session, or clears topics to effectively disconnect. Requires the client_id (session identifier) returned in the connected event from the GET request.
Request body (JSON)
| Field | Type | Required | Description |
client_id | string | Yes | Session ID returned when the SSE connection was established. |
topics | array | Yes | New list of topics. Each topic is an entity name or entity:row_id. Pass an empty array to clear subscriptions and disconnect. |
Example: Update topics
curl -X POST http://localhost:7070/api/v1/realtime \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"client_id": "sse_1769987962000_0abc1",
"topics": ["posts", "comments"]
}'
Example: Clear topics (disconnect)
curl -X POST http://localhost:7070/api/v1/realtime \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"client_id": "sse_1769987962000_0abc1", "topics": []}'
SSE event types
| Event | Description |
connected | Sent once when the SSE connection is established. Contains client_id, topics, and timestamp. |
ping | Keep-alive sent periodically (e.g. every ~30 s). Contains timestamp. |
change | A database change (insert, update, or delete) for a subscribed topic. |
Event data format
connected
{
"client_id": "sse_1769987962000_0abc1",
"topics": ["posts", "users"],
"timestamp": 1769987962
}
ping
{"timestamp": 1769988043}
change
| Field | Type | Description |
action | string | One of insert, update, delete. |
entity | string | Entity (table) name. |
row_id | string | ID of the affected row. |
topic | string | Topic that matched (entity or entity:row_id). |
timestamp | number | Unix timestamp of the change. |
data | object | null | For insert and update, the row payload; for delete, null. |
Example change (insert)
{
"action": "insert",
"data": {
"created": "2026-02-02T02:19:38",
"id": "019c1b81-364b-7000-8120-b5416b2c42c2",
"updated": "2026-02-02T02:19:38"
},
"entity": "test",
"row_id": "019c1b81-364b-7000-8120-b5416b2c42c2",
"timestamp": 1769988013,
"topic": "test"
}
Example change (delete)
{
"action": "delete",
"data": null,
"entity": "test",
"row_id": "019c1b81-1501-7000-9d65-1541c14f99b7",
"timestamp": 1769988013,
"topic": "test"
}
Access control
Realtime endpoints use the same access rules as entity list and get:
- Subscribing to an entity (e.g.
posts) requires list access on that entity.
- Subscribing to a specific row (e.g.
posts:<id>) requires get access.
Invalid or unauthorized topics result in 400 or 403 responses.
Backend support
Realtime is supported for:
- SQLite — Change detection via polling.
- PostgreSQL — Change detection via
LISTEN/NOTIFY and triggers.
🎛️ Admin Dashboard
The MantisBase Admin Dashboard is a comprehensive web-based interface accessible at /mb (e.g., http://localhost:7070/mb). It provides a visual alternative to the REST API for managing your backend.
Dashboard Features
Entity Management
- Browse Entities - View all entities (tables) in your database
- View Records - Browse, search, and filter records in any entity
- Create Records - Add new records through intuitive forms
- Edit Records - Update existing records inline
- Delete Records - Remove records with confirmation
Schema Management
- Schema Builder - Create and configure entity schemas visually
- Field Management - Add, edit, and remove fields with type selection
- Access Rules Configuration - Set up access control rules with a user-friendly interface
- Foreign Key Setup - Configure relationships between entities
- View Entity Support - Create and manage SQL view entities
Data Exploration
- Search & Filter - Quickly find records with built-in search
- Pagination - Navigate through large datasets
- Sorting - Sort records by any column
- Real-time Updates - See changes reflected immediately
User Management
- Authentication Entities - Manage auth-type entities
- User Accounts - View and manage user accounts
- Admin Accounts - Manage admin users
System Management
- Logs Viewer - Access system logs directly from the dashboard
- Health Status - Monitor system health
- Configuration - View and manage system settings
Accessing the Dashboard
- Create an Admin Account (if not already created):
./mantisbase admins add admin@example.com your_password
- Navigate to Dashboard:
- Login with your admin credentials
Dashboard Requirements
- Admin Authentication Required - Only users authenticated as admins can access the dashboard
- Modern Browser - Works best with Chrome, Firefox, Safari, or Edge (latest versions)
- JavaScript Enabled - The dashboard requires JavaScript to function