Schema Protocol¶
The admin app is entirely driven by a JSON schema served from GET /admin/schema. This endpoint is auto-generated by Craft Easy API based on your registered resources, field definitions, and access rights.
AdminSchema¶
The root schema object describes the entire admin interface:
interface AdminSchema {
version: string; // Schema version, e.g. "1.0"
title: string; // App title, e.g. "My Admin"
auth: AuthConfig; // Authentication endpoints
modules: Record<string, boolean>; // Enabled modules
theme?: ThemeConfig; // Optional theme overrides
navigation?: NavigationGroup[]; // Sidebar navigation groups
resources: ResourceSchema[]; // All available resources
}
AuthConfig¶
interface AuthConfig {
login_endpoint: string; // e.g. "/auth/login/email"
refresh_endpoint: string; // e.g. "/auth/refresh"
token_header: string; // e.g. "X-API-Key"
}
ThemeConfig¶
interface ThemeConfig {
primary_color: string; // CSS color, e.g. "#2563eb"
logo_url?: string; // URL to logo image
favicon_url?: string; // URL to favicon
}
NavigationGroup¶
Groups resources in the sidebar:
interface NavigationGroup {
label: string; // Group heading, e.g. "Users & Access"
icon?: string; // Optional icon identifier
resources: string[]; // Resource names in this group
}
ResourceSchema¶
Each resource describes one API collection and how the admin should display it:
interface ResourceSchema {
endpoint: string; // API path, e.g. "/users"
name: string; // Unique identifier, e.g. "users"
label: string; // Singular display name, e.g. "User"
label_plural: string; // Plural display name, e.g. "Users"
icon?: string; // Optional icon
description?: string; // Tooltip/help text
methods: string[]; // Allowed HTTP methods: ["GET","POST","PATCH","DELETE"]
list: ListConfig; // List view configuration
form: FormConfig; // Create/edit form configuration
fields: Record<string, FieldSchema>; // All field definitions
features: ResourceFeatures; // Enabled UI features
}
ListConfig¶
Controls how the list view displays items:
interface ListConfig {
fields: string[]; // Columns to show
search_fields: string[]; // Fields included in search
filter_fields: string[]; // Fields available as filters
sort_default: string; // Default sort field (prefix "-" for descending)
sort_fields?: string[]; // Sortable fields
page_size: number; // Items per page
}
FormConfig¶
Organizes form fields into collapsible groups:
interface FormConfig {
groups: FormGroup[];
}
interface FormGroup {
label: string; // Group heading
fields: string[]; // Fields in this group
collapsible?: boolean; // Can be collapsed
collapsed?: boolean; // Initially collapsed
}
ResourceFeatures¶
Toggles for UI capabilities:
interface ResourceFeatures {
create: boolean; // Show "Create" button
edit: boolean; // Show "Edit" button
delete: boolean; // Show "Delete" button
export: boolean; // Show "Export" button
bulk_delete: boolean; // Allow bulk selection + delete
duplicate: boolean; // Show "Duplicate" action
}
FieldSchema¶
Each field definition describes the data type, widget, validation, and display:
interface FieldSchema {
// Type & display
type: string; // "string" | "number" | "boolean" | "date" | "json"
widget: string; // Widget identifier (see Field Widgets)
required: boolean;
readonly: boolean;
label?: string; // Display label (auto-generated from field name if omitted)
placeholder?: string;
help_text?: string;
// Validation
min?: number; // Minimum value (numbers) or min date
max?: number; // Maximum value (numbers) or max date
step?: number; // Increment step for number inputs
min_length?: number; // Minimum string length
max_length?: number; // Maximum string length
pattern?: string; // Regex validation pattern
// Select options
options?: SelectOption[]; // For select/multiselect widgets
// Relations
relation?: RelationConfig; // For relation picker widget
// File upload
accept?: string; // MIME types, e.g. "image/*,.pdf"
max_size_mb?: number; // Max file size in MB
// GDPR
gdpr?: boolean; // Field contains personal data
gdpr_category?: string; // PII category
}
SelectOption¶
interface SelectOption {
value: string;
label: string;
color?: string; // Optional badge color
icon?: string; // Optional icon
}
RelationConfig¶
Configures the relation picker for foreign key fields:
interface RelationConfig {
endpoint: string; // Related resource endpoint, e.g. "/tenants"
label_field: string; // Field to display, e.g. "name"
search_field: string; // Field to search on, e.g. "name"
value_field: string; // Field to store, e.g. "id"
filters?: Record<string, string>; // Static filters applied to queries
}
How the Schema Is Generated¶
The /admin/schema endpoint is automatically built from your registered resources:
- Resource registry — every resource registered via
app.register_resource()is included - Field introspection — Pydantic model fields are converted to
FieldSchemawith type, widget, and validation rules inferred from type annotations andField()metadata - Access filtering — the schema is filtered per-user based on access rights:
- System users see all resources
- Other users only see resources they have
GETaccess to - Fields with
attribute_accesslevel"none"are removed - Fields with
"read"level becomereadonly: true features.create,features.edit,features.deleteare adjusted based on allowed methods
- ETag caching — an MD5 hash of the schema JSON is returned as an
ETagheader; clients can sendIf-None-Matchto get a304 Not Modifiedresponse