Skip to main content

YAML Syntax & Structure

flAPI extends standard YAML with section includes, environment-variable substitution, and a fixed set of top-level keys per endpoint. This guide covers the extended syntax, the supported endpoint shapes (REST + 3 MCP variants), and path resolution rules.

Extended YAML Features​

flAPI's YAML parser supports standard YAML plus these extensions:

1. Section Includes​

flAPI's include directive copies one named section out of another YAML file. The syntax is:

{{include:section_name from path/to/file.yaml}}

No quotes around the path. The path is resolved relative to the including file.

Includable sections (anything else is rejected):

  • request
  • auth
  • rate-limit
  • connection
  • template-source
  • cache
  • heartbeat

Example — a shared customer-common.yaml:

# common/customer-common.yaml
request:
- field-name: id
field-in: query
validators:
- type: int
min: 1

auth:
enabled: true
type: basic
users:
- username: admin
password: '${ADMIN_PASSWORD}'
roles: [admin, read]

rate-limit:
enabled: true
max: 100
interval: 60

connection:
- customers-parquet

template-source: customers.sql

cache:
enabled: true
table: customers_cache
schema: analytics
schedule: 5m

Endpoint that pulls them in:

# customers-rest.yaml
url-path: /customers/
method: GET

{{include:request from common/customer-common.yaml}}
{{include:auth from common/customer-common.yaml}}
{{include:rate-limit from common/customer-common.yaml}}
{{include:connection from common/customer-common.yaml}}
{{include:template-source from common/customer-common.yaml}}
{{include:cache from common/customer-common.yaml}}

with-pagination: true

You can also keep multiple variants of a section under different top-level keys in the source file (auth, auth-dev, auth-prod, ...) and choose which to include:

{{include:auth-prod from common/customer-common.yaml}}

This works because the include directive grabs the value of whatever top-level key you name.

2. Environment Variables​

Reference environment variables anywhere a value is expected. Two equivalent forms exist:

auth:
jwt-secret: '${JWT_SECRET}'
jwt-issuer: '{{env.JWT_ISSUER}}'
  • ${VAR} — shell-style.
  • {{env.VAR}} — Mustache-style, also works inside SQL templates.

Environment variables must be whitelisted in flapi.yaml (template.environment-whitelist). Unknown / unwhitelisted variables cause a load-time error.

3. Template Variables​

These context variables are available inside SQL templates (not in endpoint YAML):

  • params.* — validated request parameters
  • conn.* — properties of the first connection listed under connection:
  • auth.* — authenticated user (auth.username, auth.roles, auth.email, auth.type, auth.authenticated)
  • cache.* — cache metadata (in cache-refresh templates)
  • env.* — whitelisted environment variables

See SQL Templating for the full reference.

Endpoint YAML Structure​

Each YAML file defines one endpoint of one of four kinds. flAPI decides which kind by inspecting the top-level keys:

Top-level key presentEndpoint kind
url-pathREST
mcp-toolMCP tool
mcp-resourceMCP resource
mcp-promptMCP prompt

url-path can also coexist with mcp-tool / mcp-resource when the same query should be exposed both ways.

Basic REST Endpoint​

# sqls/customers.yaml

url-path: /customers/
method: GET

request:
- field-name: segment
field-in: query
description: Market segment to filter by
required: false
validators:
- type: enum
allowedValues: [AUTOMOBILE, BUILDING, FURNITURE, HOUSEHOLD, MACHINERY]

- field-name: min_balance
field-in: query
description: Minimum account balance
required: false
validators:
- type: int
min: 0
max: 1000000

template-source: customers.sql

connection:
- customers-parquet

with-pagination: true

cache:
enabled: true
table: customers_cache
schema: analytics
schedule: 5m
primary-key: [id]
# sqls/orders.yaml

url-path: /orders/:order_id
method: GET

request:
- field-name: order_id
field-in: path
description: Order ID
required: true
validators:
- type: int
min: 1

- field-name: status
field-in: query
description: Order status filter
required: false
default: "completed"
validators:
- type: enum
allowedValues: [pending, completed, cancelled, refunded]

- field-name: start_date
field-in: query
description: Start of the date range (YYYY-MM-DD)
required: false
validators:
- type: date
min: "2020-01-01"

- field-name: end_date
field-in: query
description: End of the date range (YYYY-MM-DD)
required: false
validators:
- type: date

template-source: orders/detail.sql
connection:
- bigquery-warehouse
- customers-parquet

with-pagination: true
request-fields-validation: true

auth:
enabled: true
type: bearer
jwt-secret: '${JWT_SECRET}'
jwt-issuer: 'my-auth-server'

rate-limit:
enabled: true
max: 1000
interval: 60

cache:
enabled: true
table: orders_cache
schema: analytics
schedule: 15m
primary-key: [order_id]
cursor:
column: updated_at
type: timestamp
retention:
keep-last-snapshots: 5
max-snapshot-age: 14d

Top-Level Keys Reference​

KeyTypeDefaultNotes
url-pathstring–Required for REST endpoints. Path parameters use :name.
methodstringGETSingle HTTP method: GET, POST, PUT, PATCH, DELETE. Use one string, not a list.
template-sourcestring–Required for REST + MCP-tool + MCP-resource. Path to .sql file.
connectionlist[string]–Required when a template is used. First entry exposes conn.* in templates.
requestlist[]Request parameter definitions.
with-paginationbooltrueWraps responses in {data, next, total_count} and accepts limit/offset.
request-fields-validationboolfalseReject requests containing parameters not declared in request:.
authmappinginherits globalPer-endpoint auth override — see Authentication.
rate-limitmappinginherits globalPer-endpoint rate-limit override.
cachemapping–DuckLake cache configuration.
operationmappingautotype: Read / type: Write, plus returns-data, transaction, validate-before-write.
heartbeatmapping–Endpoint heartbeat config.
mcp-toolmapping–Declares an MCP tool.
mcp-resourcemapping–Declares an MCP resource.
mcp-promptmapping–Declares an MCP prompt.

Note: method is a single string. There is no methods: [GET] list form.

MCP Endpoint Variants​

flAPI exposes the same YAML configuration as three MCP shapes for AI agents.

MCP Tool​

A callable tool that runs an SQL query. Only these three keys are recognised:

KeyTypeDefaultDescription
mcp-tool.namestringrequiredUnique tool name (alphanumeric / underscore)
mcp-tool.descriptionstringrequiredTool description for the LLM
mcp-tool.result-mime-typestringapplication/jsonMIME type sent back to the model
# sqls/customers-mcp.yaml
mcp-tool:
name: search_customers
description: |
Search and retrieve customer information with flexible filtering
by segment, balance, name, or registration date.
result-mime-type: application/json

request:
- field-name: segment
field-in: query
required: false
validators:
- type: enum
allowedValues: [AUTOMOBILE, BUILDING, FURNITURE, MACHINERY, HOUSEHOLD]

- field-name: min_balance
field-in: query
required: false
validators:
- type: int
min: 0
max: 1000000

- field-name: name
field-in: query
required: false
validators:
- type: string
min: 2
max: 50
regex: '^[A-Za-z ]+$'

template-source: customers/search.sql
connection:
- customers-parquet

MCP Resource​

A readable resource — e.g. an introspection query exposed as data.

KeyTypeDefaultDescription
mcp-resource.namestringrequiredUnique resource name
mcp-resource.descriptionstringrequiredDescription shown to the model
mcp-resource.mime-typestringapplication/jsonContent MIME type
mcp-resource:
name: customer_schema
description: Customer table schema and field definitions
mime-type: application/json

template-source: customers/schema.sql
connection:
- customers-parquet

MCP Prompt​

A reusable, parameterised Mustache prompt. Prompts have an inline template (no template-source) and do not need a connection.

KeyTypeDefaultDescription
mcp-prompt.namestringrequiredUnique prompt name
mcp-prompt.descriptionstringrequiredDescription shown to the model
mcp-prompt.templatestringrequiredInline Mustache template body
mcp-prompt.argumentslist[string][]Template argument names
mcp-prompt:
name: customer_analysis
description: Generate a customer analysis prompt
template: |
You are a data analyst. Analyse this customer:
{{#customer_id}}Customer ID: {{customer_id}}{{/customer_id}}
{{#segment}}Segment: {{segment}}{{/segment}}

Provide insights on purchasing patterns and recommendations.
arguments:
- customer_id
- segment

File Structure Best Practices​

project/
├── flapi.yaml # Main configuration
├── common/ # Shared section definitions
│ ├── customer-common.yaml
│ └── _shared/
│ └── auth.yaml
│
└── sqls/ # Endpoint definitions + SQL templates
├── customers/
│ ├── list.yaml # GET /customers/
│ ├── list.sql
│ ├── detail.yaml # GET /customers/:id
│ ├── detail.sql
│ └── search.yaml # MCP search tool
│
├── orders/
│ ├── list.yaml
│ ├── list.sql
│ ├── create.yaml # POST /orders/
│ └── create.sql
│
└── analytics/
├── revenue.yaml
└── revenue.sql

Naming Conventions​

sqls/customers/list.yaml      -> GET    /customers/
sqls/customers/detail.yaml -> GET /customers/:id
sqls/customers/search.yaml -> GET /customers/search/
sqls/orders/create.yaml -> POST /orders/
sqls/analytics/revenue.yaml -> GET /analytics/revenue/

Path Resolution​

Includes​

Includes resolve relative to the including file:

# flapi.yaml (project root) — main config does not use the include directive,
# it lives only inside endpoint YAML files.

# sqls/customers-rest.yaml
{{include:request from ../common/customer-common.yaml}}
# Resolves to: common/customer-common.yaml

Template Source​

template-source: resolves relative to the directory configured as template.path in flapi.yaml. Sub-paths are honoured:

# template.path: sqls/

template-source: customers.sql
# -> sqls/customers.sql

template-source: customers/list.sql
# -> sqls/customers/list.sql

Absolute paths and remote (s3://, https://, ...) paths are used as-is.

Cache Template Override​

cache:
template-file: customers_cache.sql
# Same resolution rules as template-source.

YAML Best Practices​

1. Consistent indentation​

# 2 spaces throughout
request:
- field-name: status
field-in: query
validators:
- type: enum
allowedValues: [active, inactive]

2. Comment intent, not mechanics​

# Customer search endpoint
# Cached every 5 minutes, basic auth, read-only.
url-path: /customers/search/

3. Use descriptive field names​

- field-name: customer_segment
description: Market segment classification
- field-name: minimum_account_balance
description: Minimum balance in USD
# -- Endpoint -----------------------------------------------
url-path: /customers/
method: GET

# -- Request ------------------------------------------------
request:
- field-name: id
field-in: query

# -- Caching ------------------------------------------------
cache:
enabled: true

5. Pull shared config out into common files​

{{include:auth from ../common/_shared/auth-basic.yaml}}
{{include:rate-limit from ../common/_shared/rate-limit-standard.yaml}}

6. Always validate enums and ranges​

validators:
- type: enum
allowedValues: [pending, completed, cancelled]

7. Multi-line descriptions for MCP tools​

mcp-tool:
name: search_orders
description: |
Search orders by status, customer, and date range.
Returns up to 100 orders per page (use limit/offset for more).

8. Keep secrets out of YAML​

auth:
jwt-secret: '${JWT_SECRET}' # not a literal

Validation & Testing​

Validate YAML syntax​

flapii endpoints validate /customers/

Inspect resolved paths and includes​

flapii config paths sqls/customers/list.yaml

Export resolved configuration​

flapii config export sqls/customers/list.yaml

Troubleshooting​

YAML syntax errors​

Check indentation and quoting; YAML is whitespace-sensitive.

Include not found​

Error: Include file not found: common/missing.yaml

Verify the file exists at the path relative to the including YAML, and that the section name on the left of from matches a top-level key in that file.

Environment variable not resolved​

Error: Environment variable 'DB_HOST' not found

Export the variable and add it to template.environment-whitelist in flapi.yaml.

Template path not found​

Error: Template file not found: customers.sql

Confirm template-source resolves against template.path from flapi.yaml.

Next Steps​

🍪 Cookie Settings