Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.veloiq.dev/llms.txt

Use this file to discover all available pages before exploring further.

create_crud_router generates five standard REST endpoints for any SQLModel table class and returns them as a FastAPI APIRouter. The generated router is the entire API layer for the common case — a database table with list, get, create, update, and delete operations. Each generated module’s api.py uses this function, and the module auto-loader registers the router with the FastAPI application automatically.

Generated endpoints

The URL prefix defaults to /<tablename> based on the model’s __tablename__ attribute.
MethodPathDescription
GET/{model}Paginated list. Accepts _start, _end, _sort, _order, and column filter parameters.
GET/{model}/{id}Fetch a single record by primary key.
POST/{model}Create a new record. Returns the created record with status 201.
PUT/{model}/{id}Full update — replaces all writable fields.
PATCH/{model}/{id}Partial update — sets only the fields present in the payload.
DELETE/{model}/{id}Delete a record. Returns status 204.

List endpoint

Query parameters

ParameterTypeDefaultDescription
_startint0Zero-based offset of the first record to return.
_endint25Zero-based offset of the last record (exclusive). Returns _end - _start records.

Column filters

Any query parameter whose name matches a column name on the model is applied as an exact equality filter:
GET /order?status=pending
Append __ilike to a column name for a case-insensitive contains match:
GET /order?reference__ilike=INV-2024
Parameters whose names begin with _ are reserved for pagination and are not interpreted as column filters.

Response headers

List responses include two headers required by the Refine data provider pagination convention:
HeaderFormatExample
x-total-countInteger string"42"
content-rangeitems <start>-<end>/<total>"items 0-25/42"
These headers are exposed via CORS (expose_headers in the middleware configuration) so the frontend can read them cross-origin.

Example list response

GET /task?_start=0&_end=10&status=open HTTP/1.1
Authorization: Bearer <token>

HTTP/1.1 200 OK
x-total-count: 3
content-range: items 0-3/3
Content-Type: application/json

[
  { "id": 1, "title": "Design wireframes", "status": "open", "_label": "Design wireframes" },
  { "id": 2, "title": "Write tests", "status": "open", "_label": "Write tests" },
  { "id": 3, "title": "Deploy staging", "status": "open", "_label": "Deploy staging" }
]
Every record in list and get responses includes a _label field — a human-readable string computed by the model’s build_model_str_label method. The frontend uses this for relation selectors and breadcrumbs.

Authentication

When auth_enabled is True (the default), all generated endpoints require a valid JWT Bearer token in the Authorization header. Unauthenticated requests receive a 401 response. Requests with a valid token but insufficient role permissions receive 403.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Disable auth enforcement for development by setting VELOIQ_AUTH_DISABLED=1.

Access control integration

The CRUD router integrates with all three access control layers automatically:
  • Layer 1 (global roles): The RBAC middleware checks whether the user’s roles permit the HTTP method before the endpoint handler runs. Unauthorized methods return 403.
  • Layer 2 (model-level): @model_access exceptions are enforced per-model. A Viewer that has read-only global permissions and is further restricted on a specific model via @model_access will receive 403 on forbidden actions.
  • Layer 3 (field-level): veloiq_field(read_roles=…, write_roles=…) restrictions are applied at runtime. Read-restricted fields are silently omitted from responses; write-restricted fields are silently dropped from create/update payloads.
  • ReBAC (row-level): If the model carries a @rebac decorator, the list query and single-record fetch both apply the row-level filter. Inaccessible rows return 404.

Usage

# modules/orders/api.py — AUTO-GENERATED, do not edit
from veloiq_framework.crud import create_crud_router
from .models import Order

router = create_crud_router(Order)
You can add custom endpoints to the generated router without editing api.py. Import router from api.py in your custom_api.py:
# modules/orders/custom_api.py
from fastapi import Depends, HTTPException
from sqlmodel import Session, select
from veloiq_framework import get_session
from .api import router
from .models import Order

@router.post("/{order_id}/confirm")
def confirm_order(order_id: int, session: Session = Depends(get_session)):
    order = session.get(Order, order_id)
    if order is None:
        raise HTTPException(404, f"Order {order_id} not found")
    order.status = "confirmed"
    session.add(order)
    session.commit()
    session.refresh(order)
    return order.model_dump()
The framework loader imports both api.py and custom_api.py automatically. See Custom Endpoints for the full guide.

Python API

create_crud_router signature, base models, and access control decorators.

Configuration

Configure auth, CORS, and database connection.