Build a Complete API (End-to-End)¶
Verified status as of March 28, 2026. Runtime note: FastFN auto-installs function-local dependencies from
requirements.txt/package.json; host runtimes are required infastfn dev --native, whilefastfn devdepends on a running Docker daemon. This tutorial creates a realistic endpoint with:
GETandPOST- API key auth (header)
- JSON validation
- explicit HTTP status codes
- metadata hints for OpenAPI
We will create a Python function named customer-profile.
0) Requirements¶
- FastFN running on
http://127.0.0.1:8080 - Console API enabled (
FN_CONSOLE_API_ENABLED=1) - Write access enabled (
FN_CONSOLE_WRITE_ENABLED=1) or admin token
Note: /_fn/* is the admin/control-plane API.
1) Create the function¶
curl -sS 'http://127.0.0.1:8080/_fn/function?runtime=python&name=customer-profile' \
-X POST \
-H 'Content-Type: application/json' \
--data '{"methods":["GET","POST"],"summary":"Customer profile API"}'
2) Configure policy (methods, limits, OpenAPI examples)¶
curl -sS 'http://127.0.0.1:8080/_fn/function-config?runtime=python&name=customer-profile' \
-X PUT \
-H 'Content-Type: application/json' \
--data '{
"timeout_ms": 1800,
"max_concurrency": 8,
"max_body_bytes": 262144,
"invoke": {
"methods": ["GET", "POST"],
"summary": "Read or update a customer profile",
"query": {"id": "cli_100"},
"body": "{\"email\":\"alice@example.com\"}"
}
}'
3) Store a secret in function env¶
curl -sS 'http://127.0.0.1:8080/_fn/function-env?runtime=python&name=customer-profile' \
-X PUT \
-H 'Content-Type: application/json' \
--data '{"API_SECRET":{"value":"demo-key-123","is_secret":true}}'
4) Upload working handler code¶
curl -sS 'http://127.0.0.1:8080/_fn/function-code?runtime=python&name=customer-profile' \
-X PUT \
-H 'Content-Type: application/json' \
--data '{"code":"import json\\n\\n\\ndef j(status, payload):\\n return {\\n \\"status\\": status,\\n \\"headers\\": {\\"Content-Type\\": \\"application/json\\"},\\n \\"body\\": json.dumps(payload, separators=(\\",\\", \\":\\")),\\n }\\n\\n\\ndef main(req):\\n method = str(req.get(\\"method\\") or \\"GET\\").upper()\\n query = req.get(\\"query\\") or {}\\n headers = req.get(\\"headers\\") or {}\\n env = req.get(\\"env\\") or {}\\n\\n if headers.get(\\"x-api-key\\") != env.get(\\"API_SECRET\\"):\\n return j(401, {\\"error\\": \\"unauthorized\\"})\\n\\n if method == \\"GET\\":\\n cid = query.get(\\"id\\")\\n if not cid:\\n return j(400, {\\"error\\": \\"missing query param id\\"})\\n return j(200, {\\"id\\": cid, \\"name\\": \\"Alice Example\\", \\"tier\\": \\"gold\\", \\"active\\": True})\\n\\n if method == \\"POST\\":\\n raw = req.get(\\"body\\") or \\"{}\\"\\n try:\\n payload = json.loads(raw)\\n except Exception:\\n return j(400, {\\"error\\": \\"invalid json body\\"})\\n\\n email = payload.get(\\"email\\") if isinstance(payload, dict) else None\\n if not email:\\n return j(422, {\\"error\\": \\"email is required\\"})\\n\\n return j(200, {\\n \\"updated\\": True,\\n \\"email\\": email,\\n \\"fields\\": sorted(list(payload.keys())) if isinstance(payload, dict) else [],\\n })\\n\\n return j(405, {\\"error\\": \\"method not allowed\\"})\\n"}'
5) Validate behavior¶
Unauthorized (missing key)¶
Expected: 401.
Valid GET¶
Expected: 200 + JSON profile.
Invalid POST (missing email)¶
curl -i -sS -X POST 'http://127.0.0.1:8080/customer-profile' \
-H 'x-api-key: demo-key-123' \
-H 'Content-Type: application/json' \
--data '{}'
Expected: 422.
Valid POST¶
curl -i -sS -X POST 'http://127.0.0.1:8080/customer-profile' \
-H 'x-api-key: demo-key-123' \
-H 'Content-Type: application/json' \
--data '{"email":"alice@example.com","tier":"gold"}'
Expected: 200 + updated payload summary.
6) Check OpenAPI / Swagger¶
GET /openapi.jsonshould include/customer-profileGET /docsshould show request examples (query + body)
Flow Diagram¶
flowchart LR
A["Client request"] --> B["Route discovery"]
B --> C["Policy and method validation"]
C --> D["Runtime handler execution"]
D --> E["HTTP response + OpenAPI parity"]
Objective¶
Clear scope, expected outcome, and who should use this page.
Prerequisites¶
- FastFN CLI available
- Runtime dependencies by mode verified (Docker for
fastfn dev, OpenResty+runtimes forfastfn dev --native)
Validation Checklist¶
- Command examples execute with expected status codes
- Routes appear in OpenAPI where applicable
- References at the end are reachable
Troubleshooting¶
- If runtime is down, verify host dependencies and health endpoint
- If routes are missing, re-run discovery and check folder layout
See also¶
Last reviewed:
March 28, 2026
·
Docs on fastfn.dev