Skip to content

API Overview

Fullfinity provides a REST API built with FastAPI, offering auto-generated documentation and OpenAPI schema.

FastAPI automatically generates interactive API documentation:

  • Swagger UI: http://localhost:8000/docs
  • OpenAPI JSON: http://localhost:8000/openapi.json

Most API endpoints require authentication via JWT tokens.

POST /auth/authenticate
Content-Type: application/json
{
"email": "admin@example.com",
"password": "admin"
}

The database is selected by host/subdomain or the database selector, not in the request body.

Response:

{
"message": "Authenticated",
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "bearer",
"expires_at": "2026-01-01 12:00:00 UTC"
}

Include the access token in the Authorization header:

GET /api/query/Contact
Authorization: Bearer eyJ...
POST /auth/refresh
Content-Type: application/json
{
"refresh_token": "eyJ..."
}
POST /api/query/{model}

Query records with filtering, sorting, and pagination.

Request Body:

{
"fields": ["id", "name", "email"],
"q_filter": "Q(active__eq=True)",
"order_by": ["name ASC"],
"limit": 20,
"offset": 0,
"group_by": null
}

Response:

{
"data": [
{"id": 1, "name": "John", "email": "john@example.com"},
{"id": 2, "name": "Jane", "email": "jane@example.com"}
],
"total": 150
}
POST /api/fetch/{model}/{id}

Fetch a single record with related data.

Request Body:

{
"fields": ["id", "name", "lines"],
"related": ["contact", "lines.product"]
}
POST /api/create/{model}

Request Body:

{
"name": "New Product",
"price": 99.99,
"category": 5
}

Response:

{
"id": 123,
"name": "New Product",
"display_name": "New Product"
}
PUT /api/update/{model}/{id}

Request Body:

{
"name": "Updated Product",
"price": 149.99
}
DELETE /api/delete/{model}/{id}

Bulk Create:

POST /api/bulk-create/{model}
{
"records": [
{"name": "Product 1", "price": 10},
{"name": "Product 2", "price": 20}
]
}

Bulk Update:

PUT /api/bulk-update/{model}
{
"ids": [1, 2, 3],
"values": {"active": false}
}

Bulk Delete:

DELETE /api/bulk-delete/{model}
{
"ids": [1, 2, 3]
}

Call model methods:

POST /api/execute/{model}/{method}
{
"ids": [1, 2, 3],
"request_body": {
"inputs": {},
"context": {}
}
}

Response:

{
"message": "Method executed successfully",
"result": {...}
}

Search records by display name:

POST /api/name_search/{model}
{
"term": "search term",
"limit": 10,
"filter": "Q(active__eq=True)"
}

Response:

{
"data": [
{"id": 1, "display_name": "Product A"},
{"id": 2, "display_name": "Product B"}
]
}

Trigger UI effects for field changes:

POST /api/ui-effect/{model}
{
"id": 123,
"values": {"contact": 5},
"trigger_field": "contact"
}

Response:

{
"currency": 1,
"payment_term": 2
}

Get field definitions for a model:

GET /api/get_registry/{model}

Response:

{
"name": {"type": "Char", "required": true, "max_length": 255},
"price": {"type": "Monetary", "default": 0.0},
"category": {"type": "ManyToOne", "related_model": "Category"}
}
POST /api/action-meta/{model}/{method}
{
"context": {"active_ids": [1]}
}

Returns wizard view, defaults, and confirmation metadata.

POST /api/execute/{model}/{method}
{
"request_body": {
"inputs": {"field1": "value1"},
"context": {"active_ids": [1], "active_model": "Contact"}
}
}

Export records to various formats:

POST /api/export/{model}
{
"ids": [1, 2, 3],
"fields": ["name", "email", "phone"],
"format": "xlsx"
}

Supported formats: xlsx, csv

Import records from file:

POST /api/import/{model}
Content-Type: multipart/form-data
file: <uploaded file>
mapping: {"Name": "name", "Email": "email"}
POST /api/clone/{model}
{
"id": 123
}

Reorder records (used for Kanban column reordering and List row reordering):

POST /api/resequence/{model}
{
"dropped_column_id": 3,
"after_column_id": 1,
"sequence_field": "sequence"
}

dropped_column_id is the record being moved; after_column_id is the record to place it after (null to move it first); sequence_field defaults to "sequence".

Errors return appropriate HTTP status codes:

CodeDescription
400Bad Request - Invalid parameters
401Unauthorized - Invalid or missing token
403Forbidden - Access denied
404Not Found - Record doesn’t exist
500Internal Server Error

Error response format:

{
"detail": "Error message",
"error": "ErrorType",
"traceback": "..." // Only in dev mode
}

The API does not impose request rate limiting (there are no X-RateLimit-* headers). The one availability response to handle is during a module install/upgrade: while the database is mid-operation, requests receive a 503 with a Retry-After: 5 header — back off and retry.