Documentation Index Fetch the complete documentation index at: https://mintlify.com/trailbaseio/trailbase/llms.txt
Use this file to discover all available pages before exploring further.
Overview
TrailBase automatically generates OpenAPI 3.0 specifications for your APIs, providing interactive documentation through Swagger UI and enabling API client generation.
Accessing API Documentation
Swagger UI
Access interactive API documentation at:
https://yourdomain.com/_/docs
The Swagger UI provides:
Interactive testing : Try API endpoints directly from the browser
Request/response examples : See sample data for each endpoint
Authentication : Test authenticated endpoints
Schema documentation : Explore data models and types
OpenAPI JSON
Download the raw OpenAPI specification:
curl https://yourdomain.com/openapi.json > api-spec.json
API Structure
From crates/core/src/lib.rs:
use utoipa :: OpenApi ;
#[derive( OpenApi )]
#[openapi(
info(
title = "TrailBase" ,
description = "TrailBase APIs" ,
),
nest(
(path = "/api/auth/v1" , api = crate :: auth :: AuthApi ),
(path = "/api/records/v1" , api = crate :: records :: RecordOpenApi ),
),
tags(),
)]
pub struct Doc ;
API Categories
Authentication API
Endpoints under /api/auth/v1:
POST /register - Register new user
POST /login - Login with email/password
POST /logout - Logout current user
GET /user - Get current user profile
POST /verify_email - Request email verification
POST /reset_password - Request password reset
GET /oauth/{provider} - OAuth login
GET /oauth/{provider}/callback - OAuth callback
GET /oauth/providers - List OAuth providers
Records API
Endpoints under /api/records/v1/{table}:
GET /{table} - List records
POST /{table} - Create record
GET /{table}/{id} - Get record by ID
PATCH /{table}/{id} - Update record
DELETE /{table}/{id} - Delete record
GET /files/{id} - Download file
Custom API Documentation
Document Custom Endpoints
Add OpenAPI annotations to your endpoints:
use utoipa :: { OpenApi , IntoParams , ToSchema };
#[derive( Debug , Deserialize , IntoParams )]
struct SearchQuery {
/// Search query string
#[param(example = "rust" )]
q : String ,
/// Maximum number of results
#[param(minimum = 1, maximum = 100, default = 10)]
limit : Option < i32 >,
}
#[derive( Debug , Serialize , ToSchema )]
struct SearchResult {
/// Unique identifier
id : i64 ,
/// Result title
title : String ,
/// Relevance score (0-1)
#[schema(minimum = 0, maximum = 1)]
score : f64 ,
}
/// Search for items
#[utoipa :: path(
get,
path = "/search" ,
params( SearchQuery ),
responses(
(status = 200, description = "Search results" , body = Vec < SearchResult >),
(status = 400, description = "Invalid query" ),
),
tag = "search"
)]
async fn search ( Query ( params ) : Query < SearchQuery >) -> Json < Vec < SearchResult >> {
// Implementation
}
Group Custom APIs
#[derive( OpenApi )]
#[openapi(
paths(
search,
get_recommendations,
get_trending,
),
components(
schemas( SearchResult , Recommendation , TrendingItem )
),
tags(
(name = "search" , description = "Search operations" ),
(name = "discovery" , description = "Content discovery" )
)
)]
struct CustomApi ;
Schema Generation
Derive Schema
use utoipa :: ToSchema ;
use serde :: { Deserialize , Serialize };
#[derive( Debug , Serialize , Deserialize , ToSchema )]
#[schema(example = json ! ({
"id" : 1,
"title" : "Example Post" ,
"published" : true
}))]
struct Post {
/// Unique post identifier
#[schema(minimum = 1)]
id : i64 ,
/// Post title
#[schema(min_length = 1, max_length = 200)]
title : String ,
/// Post content in Markdown
content : String ,
/// Whether the post is published
#[schema(default = false)]
published : bool ,
/// Publication date
#[schema(value_type = String , format = "date-time" )]
published_at : Option < chrono :: DateTime < chrono :: Utc >>,
/// Post tags
#[schema(example = json ! ([ "rust" , "api" ]))]
tags : Vec < String >,
}
#[derive( Debug , Serialize , Deserialize , ToSchema )]
enum PostStatus {
/// Post is in draft state
Draft ,
/// Post is published and visible
Published ,
/// Post is archived
Archived ,
}
Nested Schemas
#[derive( Debug , Serialize , ToSchema )]
struct Author {
id : i64 ,
name : String ,
email : String ,
}
#[derive( Debug , Serialize , ToSchema )]
struct PostWithAuthor {
#[serde(flatten)]
post : Post ,
/// Post author
author : Author ,
}
Response Documentation
Success Responses
#[utoipa :: path(
get,
path = "/posts/{id}" ,
responses(
(status = 200, description = "Post found" , body = Post ),
(status = 404, description = "Post not found" ),
(status = 401, description = "Unauthorized" ),
),
params(
( "id" = i64 , Path , description = "Post ID" )
)
)]
async fn get_post ( Path ( id ) : Path < i64 >) -> Result < Json < Post >, StatusCode > {
// Implementation
}
Error Responses
#[derive( Debug , Serialize , ToSchema )]
struct ErrorResponse {
/// Error message
error : String ,
/// Optional error details
details : Option < serde_json :: Value >,
}
#[utoipa :: path(
post,
path = "/posts" ,
request_body = Post ,
responses(
(status = 201, description = "Post created" , body = Post ),
(status = 400, description = "Invalid input" , body = ErrorResponse ),
(status = 401, description = "Unauthorized" ),
)
)]
async fn create_post ( Json ( post ) : Json < Post >) -> Result < Json < Post >, ( StatusCode , Json < ErrorResponse >)> {
// Implementation
}
Authentication Documentation
Bearer Token
use utoipa :: openapi :: security :: { HttpAuthScheme , HttpBuilder , SecurityScheme };
#[derive( OpenApi )]
#[openapi(
modifiers( & SecurityAddon ),
)]
struct ApiDoc ;
struct SecurityAddon ;
impl utoipa :: Modify for SecurityAddon {
fn modify ( & self , openapi : & mut utoipa :: openapi :: OpenApi ) {
if let Some ( components ) = openapi . components . as_mut () {
components . add_security_scheme (
"bearer_auth" ,
SecurityScheme :: Http (
HttpBuilder :: new ()
. scheme ( HttpAuthScheme :: Bearer )
. bearer_format ( "JWT" )
. build ()
),
)
}
}
}
#[utoipa :: path(
get,
path = "/protected" ,
responses(
(status = 200, description = "Success" ),
),
security(
( "bearer_auth" = [])
)
)]
async fn protected_endpoint () -> String {
"Protected data" . to_string ()
}
Client Generation
Generate TypeScript Client
Use openapi-typescript :
# Install
npm install -D openapi-typescript
# Generate types
npx openapi-typescript https://yourdomain.com/openapi.json -o ./src/api-types.ts
Usage:
import type { paths } from './api-types' ;
type SearchParams = paths [ '/api/search' ][ 'get' ][ 'parameters' ][ 'query' ];
type SearchResponse = paths [ '/api/search' ][ 'get' ][ 'responses' ][ '200' ][ 'content' ][ 'application/json' ];
async function search ( params : SearchParams ) : Promise < SearchResponse > {
const query = new URLSearchParams ( params as any );
const response = await fetch ( `/api/search? ${ query } ` );
return response . json ();
}
Generate Python Client
Use openapi-python-client :
pip install openapi-python-client
openapi-python-client generate --url https://yourdomain.com/openapi.json
Generate Go Client
Use oapi-codegen :
go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@latest
oapi-codegen -package api https://yourdomain.com/openapi.json > api/client.go
Testing with OpenAPI
Validate Responses
#[cfg(test)]
mod tests {
use super ::* ;
#[tokio :: test]
async fn test_openapi_spec () {
let spec = ApiDoc :: openapi ();
// Validate spec is valid OpenAPI
assert! ( spec . info . title == "TrailBase" );
assert! ( ! spec . paths . paths . is_empty ());
// Check all endpoints have responses
for ( path , item ) in spec . paths . paths . iter () {
if let Some ( operation ) = & item . get {
assert! (
! operation . responses . responses . is_empty (),
"GET {} missing responses" ,
path
);
}
}
}
}
Contract Testing
import { test , expect } from '@jest/globals' ;
import OpenAPIValidator from 'openapi-validator' ;
test ( 'API responses match OpenAPI spec' , async () => {
const spec = await fetch ( 'https://api.example.com/openapi.json' ). then ( r => r . json ());
const validator = new OpenAPIValidator ( spec );
const response = await fetch ( 'https://api.example.com/api/records/v1/posts' );
const body = await response . json ();
const validation = validator . validate ( '/api/records/v1/posts' , 'get' , response . status , body );
expect ( validation . errors ). toHaveLength ( 0 );
});
Best Practices
Document all endpoints
Add OpenAPI annotations to every public endpoint for complete documentation.
Provide examples
Include example requests and responses: #[schema(example = json ! ({
"id" : 1,
"name" : "Example"
}))]
Use descriptive tags
Group related endpoints with tags: #[utoipa :: path(
tag = "users" ,
// ...
)]
Document errors
Specify all possible error responses with status codes and error schemas.
Keep specs in sync
Run validation tests to ensure OpenAPI specs match implementation.
Version your APIs
Use path prefixes for API versioning: nest (
( path = "/api/v1" , api = ApiV1 ),
( path = "/api/v2" , api = ApiV2 ),
)
Customizing Swagger UI
The Swagger UI can be customized by modifying the HTML template in the TrailBase source:
<! DOCTYPE html >
< html >
< head >
< title > API Documentation </ title >
< link rel = "stylesheet" href = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css" >
< style >
/* Custom styles */
.swagger-ui .topbar { display : none ; }
</ style >
</ head >
< body >
< div id = "swagger-ui" ></ div >
< script src = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js" ></ script >
< script >
SwaggerUIBundle ({
url: '/openapi.json' ,
dom_id: '#swagger-ui' ,
deepLinking: true ,
presets: [
SwaggerUIBundle . presets . apis ,
SwaggerUIBundle . SwaggerUIStandalonePreset
],
});
</ script >
</ body >
</ html >
Alternative API Documentation
Redoc
Use Redoc for a different documentation style:
<! DOCTYPE html >
< html >
< head >
< title > API Reference </ title >
< script src = "https://cdn.jsdelivr.net/npm/redoc@latest/bundles/redoc.standalone.js" ></ script >
</ head >
< body >
< redoc spec-url = "/openapi.json" ></ redoc >
</ body >
</ html >
RapiDoc
RapiDoc offers a customizable API console:
<! DOCTYPE html >
< html >
< head >
< script type = "module" src = "https://unpkg.com/rapidoc/dist/rapidoc-min.js" ></ script >
</ head >
< body >
< rapi-doc
spec-url = "/openapi.json"
theme = "dark"
render-style = "view"
></ rapi-doc >
</ body >
</ html >
Next Steps
Custom Endpoints Build documented APIs
WASM Components Create custom endpoints
OAuth Providers Document auth flows
Object Storage File upload APIs