Skip to main content

Endpoints Overview

Endpoints are the heart of flAPI. Each endpoint defines a REST API that serves data from your sources. This guide covers everything you need to know about creating, configuring, and managing endpoints.

What is an Endpoint?

An endpoint is a combination of:

  1. URL path - Where clients access your API (e.g., /customers/, /orders/)
  2. SQL template - The query that retrieves and transforms data
  3. Configuration - Parameters, validation, caching, authentication

File Structure

Every endpoint consists of two files in the sqls/ directory:

project/
├── flapi.yaml # Main configuration
└── sqls/
├── customers.yaml # Endpoint configuration
├── customers.sql # SQL template
├── orders.yaml
└── orders.sql

Minimal Endpoint

The simplest possible endpoint:

sqls/hello.yaml:

url-path: /hello/
template-source: hello.sql
connection:
- my-database

sqls/hello.sql:

SELECT 'Hello, World!' as message

That's it! Start flAPI and access http://localhost:8080/hello/

Complete Endpoint Configuration

Here's a full-featured endpoint with all options:

# URL configuration
url-path: /customers/

# Request parameters
request:
- field-name: id
field-in: query
description: Customer ID to filter by
required: false
validators:
- type: int
min: 1

- field-name: segment
field-in: query
description: Market segment
required: false
validators:
- type: string
enum: ['AUTOMOTIVE', 'BUILDING', 'FURNITURE']

# SQL template
template-source: customers.sql

# Data connection
connection:
- customers-db

# Caching configuration
cache:
enabled: true
table: customers_cache
schema: analytics
schedule: 60m
template_file: customers_cache.sql

# Authentication
authentication:
required: true
methods: ['jwt', 'api-key']

# Rate limiting
rate-limit:
requests: 1000
window: 60s
per: user

# MCP tool for AI agents
mcp-tool:
name: get_customers
description: Retrieve customer data filtered by segment or ID

URL Paths

Basic Paths

url-path: /customers/
url-path: /products/search/
url-path: /analytics/revenue/

Rules:

  • Must start with /
  • Should end with / (convention)
  • Use lowercase with hyphens: /product-categories/
  • No spaces or special characters

Path Parameters

Include dynamic segments in your URL:

url-path: /customers/{id}/
request:
- field-name: id
field-in: path
required: true
validators:
- type: int

Examples:

  • /customers/123/id = 123
  • /orders/{order_id}/items/ → Order items API
  • /users/{user_id}/permissions/ → User permissions

Request Parameters

Parameters can come from different sources:

Query Parameters

Most common for filtering and search:

# /customers?segment=AUTO&active=true
request:
- field-name: segment
field-in: query
- field-name: active
field-in: query

Path Parameters

For resource identification:

# /customers/123/
request:
- field-name: id
field-in: path
required: true

Header Parameters

For authentication and metadata:

# Header: X-User-Region: US
request:
- field-name: user_region
field-in: header

Body Parameters (POST/PUT)

For data submission:

# POST /customers with JSON body
request:
- field-name: customer_data
field-in: body
required: true

SQL Templates

Connect your endpoint to a SQL template:

template-source: customers.sql

The template uses Mustache syntax for dynamic queries:

-- sqls/customers.sql
SELECT
c_custkey as id,
c_name as name,
c_mktsegment as segment
FROM customers
WHERE 1=1
{{#params.segment}}
AND c_mktsegment = '{{{params.segment}}}'
{{/params.segment}}
{{#params.id}}
AND c_custkey = {{{params.id}}}
{{/params.id}}

See SQL Templating Guide for details.

Data Connections

Specify which connection(s) to use:

Single Connection

connection:
- customers-db

Multiple Connections

Join data across sources:

connection:
- bigquery-warehouse
- customers-parquet
-- Join BigQuery orders with local customer data
SELECT
o.*,
c.name as customer_name
FROM bigquery_scan('project.dataset.orders') o
LEFT JOIN '{{{conn.customers-parquet.path}}}' c
ON o.customer_id = c.id

Response Format

flAPI returns JSON by default:

{
"data": [
{"id": 1, "name": "Customer A"},
{"id": 2, "name": "Customer B"}
],
"metadata": {
"count": 2,
"execution_time_ms": 1.2
}
}

Configure response format:

response:
format: json # or: csv, parquet
include_metadata: true
pagination:
enabled: true
max_limit: 1000

Endpoint Discovery

List All Endpoints

$ flapii endpoints list

Available Endpoints:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Path Method Cached
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
/customers/ GET Yes
/orders/ GET Yes
/products/search/ GET No
/analytics/revenue/ GET Yes
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Describe Endpoint

$ flapii endpoints describe /customers/

Endpoint: /customers/
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
URL Path: /customers/
Template: sqls/customers.sql
Connection: customers-db
Cache: Enabled (60m refresh)
Auth: Required (JWT)
Rate Limit: 1000 req/min per user

Parameters:
• segment (query, optional)
Type: string
Values: AUTOMOTIVE, BUILDING, FURNITURE

• id (query, optional)
Type: integer
Min: 1

MCP Tool: get_customers

OpenAPI Documentation

flAPI automatically generates OpenAPI (Swagger) documentation:

Access at: http://localhost:8080/docs

Features:

  • ✅ Interactive API testing
  • ✅ Request/response examples
  • ✅ Parameter documentation
  • ✅ Authentication setup
  • ✅ Export OpenAPI spec

Testing Endpoints

Validate Configuration

$ flapii endpoints validate /customers/

✓ Configuration valid
✓ SQL template found: sqls/customers.sql
✓ Connection 'customers-db' exists
✓ Parameters configured correctly
✓ Validators configured correctly

Test Query

$ flapii query run /customers/ \
--params '{"segment": "AUTOMOTIVE"}' \
--limit 5

Results (5 rows):
┌──────┬─────────────────┬─────────────┐
│ id │ name │ segment │
├──────┼─────────────────┼─────────────┤
│ 101 │ Customer A │ AUTOMOTIVE │
│ 102 │ Customer B │ AUTOMOTIVE │
...

Call API Directly

$ curl http://localhost:8080/customers/?segment=AUTOMOTIVE

{
"data": [
{
"id": 101,
"name": "Customer A",
"segment": "AUTOMOTIVE"
}
]
}

Common Patterns

Pagination

request:
- field-name: limit
field-in: query
validators:
- type: int
min: 1
max: 100
- field-name: offset
field-in: query
validators:
- type: int
min: 0
SELECT * FROM products
LIMIT {{{params.limit|100}}}
OFFSET {{{params.offset|0}}}
request:
- field-name: search
field-in: query
validators:
- type: string
max_length: 100
SELECT * FROM products
WHERE name ILIKE '%{{{params.search}}}%'

Date Ranges

request:
- field-name: start_date
field-in: query
validators:
- type: string
pattern: '^\d{4}-\d{2}-\d{2}$'
- field-name: end_date
field-in: query
validators:
- type: string
pattern: '^\d{4}-\d{2}-\d{2}$'
SELECT * FROM orders
WHERE order_date BETWEEN '{{{params.start_date}}}'
AND '{{{params.end_date}}}'

Best Practices

1. Use Descriptive URL Paths

# ✅ Good
url-path: /customers/by-segment/
url-path: /orders/recent/
url-path: /analytics/monthly-revenue/

# ❌ Bad
url-path: /api1/
url-path: /data/
url-path: /query/

2. Document Parameters

- field-name: status
field-in: query
description: Filter orders by status (pending, completed, cancelled)
required: false

3. Always Validate Input

validators:
- type: string
enum: ['active', 'inactive']
- type: int
min: 1
max: 10000

4. Use Caching for Read-Heavy Endpoints

cache:
enabled: true
schedule: 60m # Hourly refresh

5. Add Rate Limiting

rate-limit:
requests: 1000
window: 60s
sqls/
├── customers/
│ ├── list.yaml
│ ├── list.sql
│ ├── detail.yaml
│ └── detail.sql
└── orders/
├── list.yaml
└── list.sql

Troubleshooting

Endpoint Not Found

Error: 404 - Endpoint not found

Check:

  1. File exists: sqls/endpoint.yaml
  2. URL path matches: url-path: /endpoint/
  3. flAPI server restarted after changes

Template Error

Error: Template expansion failed

Check:

  1. SQL file exists: template-source: endpoint.sql
  2. Mustache syntax correct
  3. Test with: flapii templates expand /endpoint/

Connection Error

Error: Connection 'my-db' not found

Check:

  1. Connection defined in flapi.yaml
  2. Connection name matches: connection: [my-db]
  3. Connection initialized properly

Next Steps

🍪 Cookie Settings