Definition Structure
A Custom API definition is a single YAML file with six top-level sections.
identifiers: # who owns this definition
permission: # who can call this endpoint
http: # URL, method, version
logic: # ordered execution steps
config: # runtime behaviour
database: # connection config
identifiers
Ties the definition to its organizational context. All five fields are required.
identifiers:
org_id: 01KC11784DW133S3THR7JTQNQ1
project_id: 01KC11KZ6VDMMKJZ4YWQYKYZ6Z
feature_id: 01KBY3K8RQ9GS1VD9XYXHZ92QT
space_id: 01KBY3K97GMAJFBQ0PP7158NZH
user_id: 01KBY3K9NDC5XW523M2V1Z0373
| Field | Description |
|---|---|
org_id | Organization owning this definition |
project_id | Project within the organization |
feature_id | Unique identifier for this definition — generate a new ULID for each |
space_id | Unique identifier for this Workspace — user workspace, dev, staging, or prod |
user_id | User creating or last modifying this definition |
All IDs use ULID format. See ID Format.
permission
Roles allowed to call this endpoint. Uses OR logic — the user needs any one matching role.
permission:
[ power, admin ]
At runtime, Minimal reads X-User-Roles from the request header and checks for a match:
X-User-Roles: editor,admin
permission: [ power, admin ]
→ admin ∈ [ power, admin ] ✅ Allowed
If no role matches, Minimal returns 403 Forbidden.
Definition management endpoints (create, update, delete) always require power or admin regardless of what is set here.
http
Defines the endpoint URL, method, and input format.
http:
uri: users/all
method: get
version: 0.1
input_type: json
| Field | Values | Description |
|---|---|---|
uri | String | Final path segment only — no leading slash, no org or project prefix |
method | get post put patch delete | HTTP method |
version | Semver string | Used for rollback — increment on each update |
input_type | json | Expected request body format |
The registered endpoint URL is:
{method} {yourdomain}/{org_abbreviation}/{project_abbreviation}/{uri}
For example, with org abbreviation lbl, project abbreviation crm, and uri: users/all:
GET https://your-domain.com/lbl/crm/users/all
logic
An ordered list of execution steps. See Logic Steps for full details.
logic:
- sql: |
SELECT * FROM users
omit: true
- lark: transform
omit: false
code: |
result = [{"id": row["id"]} for row in step_0]
Three step types are available — sql, lark, and expr.
config
Controls runtime behaviour for this endpoint.
config:
coalesce: false
rollback_version: 0.1
cache_result: true
| Field | Default | Description |
|---|---|---|
rollback_version | — | Version to revert to if this definition fails |
cache_result | false | Cache the response for repeated identical requests |
database
Connection config for the database this endpoint queries.
database:
type: mysql
source_ip: localhost
port: "3306"
username: john
password: 'pas****'
name: my_database
timeout_secs: 30
idle_timeout_secs: 600
max_open_connections: 50
max_idle_connections: 25
| Field | Description |
|---|---|
type | clickhouse, postgres, or mysql |
source_ip | Database host |
port | Port as a string |
username | Database user |
password | Encrypted password — never plaintext |
name | Database name |
timeout_secs | Query timeout in seconds |
idle_timeout_secs | How long idle connections are kept alive |
max_open_connections | Maximum connections in the pool |
max_idle_connections | Idle connections to retain in the pool |
Passwords in database.password must be encrypted. Treat them the same as database credentials — never commit plaintext values.