Fraya API Surface
Agent-oriented map of the HTTP endpoints currently exposed by this application.
Use this page as the fastest way to answer:
- what can this app already do over HTTP;
- which endpoint to call for a given task;
- what data shape to expect back;
- which endpoints are intended as stable integration points vs internal helpers.
Decision guide
If you need to:
- inspect or render a prompt from the repository → use
/api/prompts/:name - get the current curated Synthesia template registry for video generation → use
/api/video/templates - send an arbitrary system/user prompt bundle to the Dify runtime → use
/api/run
Stable integration endpoints
These endpoints are intended to be used by agents, workflows, or external tooling.
GET /api/prompts/:name
Returns prompt metadata and the stored prompt body from prompts/.
Use when:
- you need to discover which variables a prompt expects;
- you need prompt metadata before building a request;
- you need to inspect the current stored prompt definition.
Response shape:
{
"name": "tool_synthesia_choose_template",
"type": "dynamic",
"version": 3,
"variables": [
{ "name": "available_templates", "description": "..." }
],
"example_request": {
"available_templates": "Example content"
},
"output": {
"format": "json",
"schema": "{ ... }"
},
"components": [],
"system": "You are ...",
"user": "- Course title: {{ course_title }}"
}
Notes:
- The external API always returns
systemanduser. - If a prompt file is authored as a single-message
prompt, the API normalizes it to:system: ""anduser: "<prompt text>". example_requestis a generated mock payload shaped from the declaredvariables. Use it as a starting point for POST bodies, especially for nested objects and arrays.- This endpoint reads prompt YAML from the repository. It does not execute a model.
POST /api/prompts/:name
Renders a stored prompt with runtime variables substituted.
Use when:
- a workflow needs the current prompt text from the repo;
- you want Dify or another orchestrator to consume prompt instructions over HTTP instead of copying them manually;
- you need injection content already resolved into the rendered result.
Request body:
{
"course": {
"title": "Le 7 abitudini per essere più efficace"
},
"section": {
"title": "La vittoria pubblica: dall'io al noi"
}
}
Response shape:
{
"system": "You are ...",
"user": "- Course title: Le 7 abitudini per essere più efficace\n- Video title: La vittoria pubblica: dall'io al noi"
}
Error behavior:
404 Not Foundif the prompt name does not exist:
{
"code": "PROMPT_NOT_FOUND",
"message": "Prompt \"tool_missing\" not found"
}
400 Bad Requestif the request body is not a valid JSON object:
{
"code": "INVALID_JSON_BODY",
"message": "Request body must be a valid JSON object."
}
422 Unprocessable Entityif required template expressions remain unresolved after rendering:
{
"code": "UNRESOLVED_TEMPLATE_EXPRESSIONS",
"message": "Prompt render failed because required variables are missing or unresolved.",
"unresolved": ["template_id", "template_title"],
"missing_variables": ["template_id", "template_title"],
"rendered_partial": {
"system": "You are ... {{ template_id }} ...",
"user": "Template: {{ template_title }}"
}
}
Notes:
- The renderer supports nested paths (
{{ course.title }}), conditionals, loops, basic comparisons,or/and, and|length. - POST bodies may use nested JSON objects and arrays; flat dotted keys remain accepted for compatibility.
- Missing variables now cause
POSTto fail with422if they leave unresolved template expressions, for example{{ section.title }}or{{ template_id }}. missing_variablescontains unresolved expressions that look like variable paths and are absent from the input body.- This endpoint is both a renderer and a final prompt-readiness validator.
- It is the correct endpoint to use when a workflow wants prompt logic from the repo.
- The rendered response always uses the pair
system+user.
Reusable Dify helper:
- A reusable workflow wrapper around this endpoint is stored in
workflows/fraya/render-prompt/render-prompt.raw.yml. - Use that workflow when Dify needs prompt loading + input validation + normalized
system_prompt/user_promptoutputs as a reusable subflow.
GET /api/video/templates
Builds the current video template registry for the Synthesia workflow.
Use when:
- a workflow needs the curated list of supported Synthesia templates;
- you want live Synthesia metadata without using Google Sheets;
- you need a repo-controlled allowlist combined with current workspace template data.
What it does:
- Fetches the full template catalog from Synthesia using server-side credentials.
- Filters it by Fraya's curated allowlist of supported template IDs.
- Splits the result into
presentationsandtalking_head. - Returns the filtered live metadata.
Response shape:
{
"registry_source": "repo_allowlist_plus_synthesia",
"allowed_template_ids_count": 34,
"workspace_templates_count": 112,
"selected_templates_count": 34,
"presentations": [
{
"template_id": "0c471c30-f3fe-432b-9fae-642b096238c1",
"template_title": "A-F",
"template_description": "Single principle or idea — no enumeration",
"template_variables": [
{ "label": "slide_1_script", "type": "string" }
]
}
],
"talking_head": [
{
"template_id": "9c23e3c3-401b-4373-9ca2-e15b669974a3",
"template_title": "[de] Talking head (A-Q-A-F)",
"template_description": "...",
"template_variables": [
{ "label": "slide_1_script", "type": "string" }
]
}
],
"legacy_language_filtering": false,
"requested_language": "Default (auto detection)",
"requested_format": "VideoTalkingHead",
"note": "language and format are currently informational only; filtering is based on the repo allowlist and runtime consumers can still select the needed subset."
}
Optional query params:
languageformat
Current behavior:
- accepted for compatibility and debugging;
- currently informational only;
- filtering is driven by the repo allowlist, not by language-specific registry columns.
Important:
- This endpoint is the intended replacement for the old Google Sheets-based template allowlist.
- Synthesia remains the source of live metadata (
title,description,variables). - The repository remains the source of truth for which template IDs are allowed.
Internal helper endpoint
This endpoint exists and works, but should be treated as a thinner runtime helper, not the primary repo-integration surface.
POST /api/run
Proxies a raw { model, system, user } request to the configured Dify workflow runtime.
Use when:
- you want to quickly execute a prompt bundle against the Dify backend from the docs app;
- you need an internal testing surface for prompt execution.
Request body:
{
"model": "gemini-2.5-pro",
"system": "You are ...",
"user": "..."
}
Notes:
- This endpoint depends on
DIFY_API_URLandDIFY_API_KEY. - It is less repository-centric than
/api/prompts/:name. - Prefer
/api/prompts/:namewhen the task is about loading prompt logic from the repo.
Environment variables
Current endpoints depend on these server-side variables:
| Variable | Used by | Purpose |
|---|---|---|
DIFY_API_URL | /api/run | Target Dify workflow execution endpoint |
DIFY_API_KEY | /api/run | Auth for the Dify runtime |
SYNTHESIA_API_BASE_URL | /api/video/templates | Base URL for Synthesia API |
SYNTHESIA_API_KEY | /api/video/templates | Auth for server-side Synthesia template fetch |
Recommended usage patterns
- For workflow prompt loading: call
/api/prompts/:name - For video template discovery: call
/api/video/templates - For ad hoc execution from the docs app: call
/api/run
The intended long-term pattern is:
repo prompts + repo-controlled template registry + workflow orchestration in Dify