zoxaAI
Homepage
API ReferenceAgents

List agent templates

GET /api/v1/agents/templates — built-in agent starter templates.

GET /api/v1/agents/templates

Return the catalog of built-in agent templates. Templates are starting points — a partial config seed plus a base system_prompt that you fill in with a name, tweak, and save as a new agent via POST /agents.

Authentication

X-API-Key: zsk_...

Response

{
  "templates": [
    {
      "slug": "sales-qualifier",
      "name": "Sales qualifier",
      "description": "Asks 3 qualification questions and hands off if qualified.",
      "icon": "phone",
      "category": "sales",
      "system_prompt": "You are {{agentName}}, a sales qualifier for ...",
      "config": {
        "greeting": { "firstMessages": ["Hi, this is {{agentName}}..."] },
        "llm": { "provider": "openai", "model": "gpt-5.4-mini" },
        "tts": { "provider": "elevenlabs" },
        "stt": { "provider": "soniox" }
      }
    }
  ]
}
FieldNotes
slug / name / description / categoryCatalog metadata for rendering the template picker.
iconIcon name for the template card.
system_promptTop-level sibling — not nested in config. The base prompt with a {{agentName}} placeholder.
configA partial AgentConfig seed (camelCase) — a starting point, not a complete body.

Substitute {{agentName}} client-side

The consumer substitutes the chosen {{agentName}} into system_prompt and each entry of config.greeting.firstMessages client-side, then POSTs { ...config, name, systemPrompt: substituted } to POST /agents. system_prompt is passed as the top-level systemPrompt field — it is not part of the seed config.

Examples

curl https://dashboard.zoxa.ai/api/v1/agents/templates \
  -H "X-API-Key: zsk_..."
const { templates } = await fetch(
  "https://dashboard.zoxa.ai/api/v1/agents/templates",
  { headers: { "X-API-Key": "zsk_..." } },
).then((r) => r.json());

// Use the first template: substitute {{agentName}} client-side, then POST.
const t = templates[0];
const agentName = "My copy";
const systemPrompt = t.system_prompt.replaceAll("{{agentName}}", agentName);
const config = { ...t.config };
if (config.greeting?.firstMessages?.length) {
  config.greeting = {
    ...config.greeting,
    firstMessages: config.greeting.firstMessages.map((m) =>
      m.replaceAll("{{agentName}}", agentName),
    ),
  };
}

const created = await fetch("https://dashboard.zoxa.ai/api/v1/agents", {
  method: "POST",
  headers: { "X-API-Key": "zsk_...", "Content-Type": "application/json" },
  body: JSON.stringify({ ...config, name: agentName, systemPrompt }),
}).then((r) => r.json());
import httpx
templates = httpx.get(
    "https://dashboard.zoxa.ai/api/v1/agents/templates",
    headers={"X-API-Key": "zsk_..."},
).json()["templates"]

# Use the first template: substitute {{agentName}} client-side, then POST.
t = templates[0]
agent_name = "My copy"
system_prompt = t["system_prompt"].replace("{{agentName}}", agent_name)
config = dict(t["config"])
greeting = config.get("greeting")
if greeting and greeting.get("firstMessages"):
    config["greeting"] = {
        **greeting,
        "firstMessages": [
            m.replace("{{agentName}}", agent_name) for m in greeting["firstMessages"]
        ],
    }

httpx.post(
    "https://dashboard.zoxa.ai/api/v1/agents",
    headers={"X-API-Key": "zsk_..."},
    json={**config, "name": agent_name, "systemPrompt": system_prompt},
)

On this page