API Layer¶
Stable surface, with documented limits. Aksara generates HTTP endpoints from models. A ViewSet selects the model and configures the generated handlers; a serializer validates and represents model data; permissions decide whether a request may proceed. Your application authenticates the caller and attaches the server-owned identity before those checks run.
Build your first API¶
Follow the first project to create a PostgreSQL-backed ticket API, apply its migration, attach a local development identity, and exercise authenticated requests. Continue with the ticket desk tutorial for relationships and custom validation, then tenant isolation.
These chapters grow one executable application. They include the configuration, registration, database setup, and request headers needed to run the examples.
Generated endpoints¶
For a ViewSet explicitly registered with prefix = "/api/tickets", the standard
CRUD routes are:
| Method | Route | Purpose |
|---|---|---|
| GET | /api/tickets/ |
List records |
| POST | /api/tickets/ |
Create a record; success is 201 |
| GET | /api/tickets/{pk} |
Retrieve one record |
| PATCH | /api/tickets/{pk} |
Update supplied fields |
| DELETE | /api/tickets/{pk} |
Delete a record; success is 200 |
There is no generated PUT handler. Detail routes have no trailing slash.
A lifecycle-event stream is also registered at /api/tickets/stream unless
stream_enabled = False. The introductory tutorial disables that stream and
MCP exposure explicitly. Consult ViewSets for checked registration
examples and the actual customization hooks.
Choose the layer to customize¶
| Need | Start here | Boundary |
|---|---|---|
| Select a model, prefix, fields, or CRUD serializer | ViewSets | Use the operation-specific serializer attributes; serializer_class is not a supported switch. |
| Normalize or validate model data | Serializers | Validation does not authenticate the caller or establish tenant ownership. Extra input is not universally rejected. |
| Establish identity | Authentication | Password/session helpers do not install login routes or token-verification middleware. |
| Restrict requests and objects | Permissions | Hooks are synchronous; list filtering and object access are separate concerns. |
| Add a custom endpoint | Actions | Registration enforces declared request and object permissions; application code still owns query scope and field policy. |
| Register endpoints | Routing | Registration makes routes available; it does not establish caller identity. |
| Handle rejected or failed requests | Exceptions and responses | Validation, HTTP and database errors do not share one response envelope. |
| Understand identity, tenancy, and policy together | Identity concepts | Resolve identity and tenant membership on the server. |
Custom HTTP action boundary¶
Registered @action HTTP handlers run their effective permission list before
dispatch. An action override replaces the ViewSet list; None inherits it.
Detail actions also evaluate declared object permissions. Custom writes must
still enforce application-specific tenant, payload, and transaction
requirements that cannot be inferred from the decorator.
Generated CRUD and MCP execution have their own enforcement paths. MCP approval metadata does not install an HTTP approval workflow, and exposing a method over both transports does not prove equivalent authorization behavior.
Handle errors at the right boundary¶
A malformed request, a denied action and a database constraint failure are
separate cases. Generated permission checks return 403; request validation and
Aksara validation errors return 422 with different JSON structures. Send
Accept: application/json and test the actual endpoint's response instead of
assuming one universal error object. The error reference
includes executable examples and explains which exception families to catch.
Unexpected failures should remain visible to application diagnostics; a blanket
retry is not a recovery policy for writes.
Test the application boundary¶
Use the tutorial's authenticated HTTP tests and negative cases, including anonymous requests, another tenant's identifiers, and forbidden fields. Route registration or generated OpenAPI alone does not prove those controls work. Interactive API documentation is available when enabled by the application's FastAPI configuration; it is an exploration tool, not an authorization test.