HTTP API
CamusDB exposes JSON endpoints for automation and application integration. Request and response properties use camelCase.
Status And Errors
Successful responses use:
{
"status": "ok"
}
Failed responses use HTTP 500 and include a CamusDB error code when available:
{
"status": "failed",
"code": "CADB0400",
"message": "error message"
}
See Error Codes for the reference list and when each code is generated.
Column Values
Rows, filters, inserts, updates, defaults, and SQL parameters use ColumnValue
objects:
ColumnType is serialized as its numeric enum value: 0 null, 1 id, 2
int64, 3 string, 4 bool, and 5 float64.
{ "type": 3, "strValue": "R2-D2", "longValue": 0, "floatValue": 0, "boolValue": false }
{ "type": 2, "strValue": null, "longValue": 1977, "floatValue": 0, "boolValue": false }
{ "type": 5, "strValue": null, "longValue": 0, "floatValue": 12.5, "boolValue": false }
{ "type": 4, "strValue": null, "longValue": 0, "floatValue": 0, "boolValue": true }
{ "type": 1, "strValue": "507f1f77bcf86cd799439011", "longValue": 0, "floatValue": 0, "boolValue": false }
Health
GET /ping
Returns server status and UTC time.
{
"status": "ok",
"dateTime": "2026-05-28T18:30:00.0000000Z"
}
Databases
Databases must be created explicitly before table DDL, DML, or queries can use their name.
POST /create-db
{
"databaseName": "app",
"ifNotExists": true
}
POST /drop-db
{
"databaseName": "app"
}
The direct endpoint drops an existing database. For idempotent drops, use SQL:
{
"sql": "DROP DATABASE IF EXISTS app"
}
Database rename is also exposed through SQL:
{
"sql": "RENAME DATABASE app TO app_prod"
}
POST /close-db
{
"databaseName": "app"
}
Tables
POST /create-table
{
"databaseName": "app",
"tableName": "robots",
"ifNotExists": true,
"columns": [
{ "name": "id", "type": "id", "notNull": true, "defaultValue": null },
{ "name": "name", "type": "string", "notNull": true, "defaultValue": null },
{
"name": "year",
"type": "int64",
"notNull": false,
"defaultValue": {
"type": 2,
"strValue": null,
"longValue": 2024,
"floatValue": 0,
"boolValue": false
}
}
]
}
The HTTP table-creation model accepts string, int64, bool, and id.
FLOAT64 is available in SQL.
SQL Execution
Use the SQL endpoints when possible. They exercise the same parser and executor used by the engine tests.
Autocommit SQL requests use Serializable isolation by default. For requests
that start an autocommit transaction, isolationLevel can be set to
"Serializable" or "ReadCommitted", and transactionMode can be set to
"ReadWrite" or "ReadOnly". These fields are ignored when the request
resumes an existing transaction with txnIdPT and txnIdCounter.
POST /execute-sql-ddl
For schema-changing SQL:
{
"databaseName": "app",
"sql": "CREATE TABLE IF NOT EXISTS robots (id OID PRIMARY KEY NOT NULL, name STRING NOT NULL, year INT64)",
"parameters": null
}
Server-level database statements can omit databaseName:
{
"sql": "CREATE DATABASE IF NOT EXISTS app",
"parameters": null
}
POST /execute-sql-query
For SELECT statements:
{
"databaseName": "app",
"sql": "SELECT id, name FROM robots WHERE year >= @year ORDER BY name ASC",
"isolationLevel": "Serializable",
"transactionMode": "ReadOnly",
"parameters": {
"@year": {
"type": 2,
"strValue": null,
"longValue": 1970,
"floatValue": 0,
"boolValue": false
}
}
}
Response:
{
"status": "ok",
"total": 1,
"rows": [
{
"id": { "type": 1, "strValue": "507f1f77bcf86cd799439011", "longValue": 0, "floatValue": 0, "boolValue": false },
"name": { "type": 3, "strValue": "R2-D2", "longValue": 0, "floatValue": 0, "boolValue": false }
}
]
}
POST /execute-sql-non-query
For INSERT, UPDATE, and DELETE statements:
{
"databaseName": "app",
"sql": "UPDATE robots SET name = @name WHERE id = @id",
"parameters": {
"@name": { "type": 3, "strValue": "Artoo", "longValue": 0, "floatValue": 0, "boolValue": false },
"@id": { "type": 1, "strValue": "507f1f77bcf86cd799439011", "longValue": 0, "floatValue": 0, "boolValue": false }
}
}
Response:
{
"status": "ok",
"rows": 1
}
Direct Row Operations
Direct endpoints accept filters instead of SQL strings. Filters contain a
column name, an operator, and a ColumnValue.
OrderType is also numeric: 0 ascending and 1 descending.
{
"columnName": "year",
"op": ">=",
"value": {
"type": 2,
"strValue": null,
"longValue": 1970,
"floatValue": 0,
"boolValue": false
}
}
POST /insert
{
"databaseName": "app",
"tableName": "robots",
"values": {
"id": { "type": 1, "strValue": "507f1f77bcf86cd799439011", "longValue": 0, "floatValue": 0, "boolValue": false },
"name": { "type": 3, "strValue": "R2-D2", "longValue": 0, "floatValue": 0, "boolValue": false },
"year": { "type": 2, "strValue": null, "longValue": 1977, "floatValue": 0, "boolValue": false }
}
}
POST /query
{
"databaseName": "app",
"tableName": "robots",
"filters": [
{
"columnName": "year",
"op": ">=",
"value": { "type": 2, "strValue": null, "longValue": 1970, "floatValue": 0, "boolValue": false }
}
],
"orderBy": [
{ "columnName": "year", "type": 1 }
]
}
POST /query-by-id
{
"databaseName": "app",
"tableName": "robots",
"id": "507f1f77bcf86cd799439011"
}
POST /update
{
"databaseName": "app",
"tableName": "robots",
"values": {
"name": { "type": 3, "strValue": "Artoo", "longValue": 0, "floatValue": 0, "boolValue": false }
},
"filters": [
{
"columnName": "id",
"op": "=",
"value": { "type": 1, "strValue": "507f1f77bcf86cd799439011", "longValue": 0, "floatValue": 0, "boolValue": false }
}
]
}
POST /delete
{
"databaseName": "app",
"tableName": "robots",
"filters": [
{
"columnName": "year",
"op": "<",
"value": { "type": 2, "strValue": null, "longValue": 1970, "floatValue": 0, "boolValue": false }
}
]
}
Explicit Transactions
Start a transaction:
POST /start-transaction
{
"databaseName": "app",
"isolationLevel": "Serializable",
"transactionMode": "ReadWrite"
}
isolationLevel and transactionMode are optional. If omitted, the transaction
starts with the server default isolation level, which is Serializable, and the
default transaction mode, which is read-write.
Use "ReadCommitted" only when you intentionally opt down from the default
Serializable behavior. Use "ReadOnly" with "Serializable" for a stable
snapshot transaction.
Response:
{
"status": "ok",
"txnIdPT": 123,
"txnIdCounter": 1
}
Pass txnIdPT and txnIdCounter to subsequent SQL or direct row requests to
reuse that transaction:
{
"databaseName": "app",
"txnIdPT": 123,
"txnIdCounter": 1,
"sql": "INSERT INTO robots (id, name) VALUES (GEN_ID(), \"K-2SO\")"
}
Commit or roll back:
POST /commit-transaction
{
"databaseName": "app",
"txnIdPT": 123,
"txnIdCounter": 1
}
POST /rollback-transaction
{
"databaseName": "app",
"txnIdPT": 123,
"txnIdCounter": 1
}