Common API tasks
These examples use curl and assume your API key is in an environment variable:
export FYAI_API_KEY=fyai_...
export AGENT=https://agent.fyai.co.nz
export CATALOG=https://catalog.fyai.co.nz
The key needs Write access for anything that creates or runs something. See Authentication. Everything you create lands in the key's project and appears in the web app straight away.
Create an agent
An agent needs a model to run on. List the LLM configs available in your project and pick one:
curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/llmconfigs" | jq '.[] | {id, name, model, is_folder}'
Use an entry where is_folder is false. Then create the agent:
curl -s -X POST "$AGENT/agents" \
-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
-d '{
"name": "Release Notes Writer",
"path": "/docs",
"system_message": "You turn lists of merged changes into short, plain-English release notes.",
"description": "Writes customer-facing release notes.",
"llm_config": 12,
"tags": ["docs"]
}'
name, path, system_message and llm_config are required. llm_config takes the config's ID or its exact name. The response is the full agent, including its id.
Optional fields you're likely to use:
| Field | Purpose |
|---|---|
functions | List of function IDs to give the agent as tools. You can also add them later with POST /agents/{id}/functions. See Adding tools to agents. |
integration_ids | Integrations whose credentials the agent may use. |
approval_mode | always_require or never_require for tool-call approval. Leave it out to inherit. |
memory_enabled | true to give the agent memory across conversations. |
repository_ids | Repositories the agent works on. See GitHub repositories. |
introduction_message, suggested_prompts | What the agent shows before the first message in the web app. |
Every agent setting is described in Agent settings. To change an agent later, PATCH /agents/{id} with only the fields you want to change.
Before running it, you can check the agent is runnable without calling the model:
curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/agents/42/readiness"
{ "ready": true, "reasons": [], "llm_config": { "id": 12, "model": "...", "is_platform_managed": true } }
If ready is false, reasons says why — usually a missing model credential.
Run an agent once
For a quick, single-turn answer, call the synchronous endpoint:
curl -s -X POST "$AGENT/agents/42/run" \
-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
-d '{"message": "Write release notes for: fixed login timeout; added CSV export."}'
{
"output": "This release fixes…",
"agent_name": "Release Notes Writer",
"status": "completed",
"messages": [ … ],
"session_messages": [ … ],
"usage": { "input_tokens": 812, "output_tokens": 164, "total_tokens": 976, "cost_millicents": 0 },
"error_info": null
}
| Request field | Purpose |
|---|---|
message | Required. What you're asking the agent. |
llm_config_override_id | Run on a different LLM config for this call only. |
prior_messages | Earlier turns, to continue a conversation. See below. |
mission_id | Attach the run to a mission. |
output is the agent's final answer. usage is what the run was billed. When a run fails, error_info describes why (for example a model timeout or a context-length limit).
Synchronous runs hold the HTTP request open. If the agent uses tools or the answer is long, it can take longer than the ~100-second connection limit, so use the asynchronous version below.
Run an agent asynchronously
Start the run:
curl -s -X POST "$AGENT/agents/42/run-async" \
-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
-d '{"message": "Review the open issues and summarise the top three risks."}'
{ "execution_id": "3f9c2a7e5b1d4c0e8a6f2b9d7c5e1a30", "status": "pending" }
Then poll every 15 seconds or so:
curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/agents/run-async/3f9c2a7e5b1d4c0e8a6f2b9d7c5e1a30"
status | Meaning |
|---|---|
pending | Still running. Poll again. |
completed | result holds the same object the synchronous run returns. |
error | error holds the failure message. |
A finished result can be read repeatedly for about two hours, then it's removed. Only callers in the same organisation can read it.
Continue a conversation
Agent runs are stateless. To ask a follow-up, pass the previous response's session_messages back as prior_messages:
import os, requests
agent = "https://agent.fyai.co.nz"
headers = {"X-API-Key": os.environ["FYAI_API_KEY"]}
first = requests.post(f"{agent}/agents/42/run", headers=headers,
json={"message": "Draft release notes for v2.3."}).json()
second = requests.post(f"{agent}/agents/42/run", headers=headers, json={
"message": "Make it shorter and add a heading.",
"prior_messages": first["session_messages"],
}).json()
print(second["output"])
Chat with a team
A chat session is what the web app's Chat uses. Creating one over the API runs the first message in the background and records the whole conversation, so you can open it in the web app afterwards.
curl -s -X POST "$AGENT/chat/start" \
-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \
-d '{
"chat_type": "group",
"team_configuration_id": 7,
"initial_message": "Research our three main competitors and compare their pricing.",
"start_run": true
}'
| Field | Purpose |
|---|---|
chat_type | group for a team (with team_configuration_id), or agent for a single agent (with target_agent_id). |
initial_message | Required. The first message. |
start_run | Set true from code. Without it the session waits for a browser to connect and the message isn't processed. |
llm_config_override_id | For single-agent chats only: use a different LLM config for this session. |
is_autonomous | true for a run with no human participant. |
The response is the session, including its id. Then follow it:
# Is a run still executing?
curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/chat/1234" | jq '{status, run_alive, display_state}'
# The transcript so far
curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/chat/1234/conversations" | jq '.[] | {role, content}'
run_alive is true while a run is executing. display_state is one of running, failed, idle or done.
If the run stops to ask for a tool-call approval, answer it in the web app, or with POST /chat/{id}/approval and a body of {"approved": true} or {"approved": false}. To stop the run and end the session, call DELETE /chat/{id}/end.
Sending further messages into an existing chat session uses the web app's WebSocket protocol, which isn't documented as a public interface. For scripted multi-turn work, use agent runs with prior_messages.
Run a workflow and track it
Every workflow run is tracked as a mission. Starting a run is two calls: create the mission in the catalog API, then ask the agent API to execute it.
-
Find the workflow and the inputs it takes:
curl -s -H "X-API-Key: $FYAI_API_KEY" "$CATALOG/workflows" | jq '.[] | {id, name}'curl -s -H "X-API-Key: $FYAI_API_KEY" "$CATALOG/workflows/88" | jq '.attributes' -
Optionally check it's ready to run:
curl -s -H "X-API-Key: $FYAI_API_KEY" "$AGENT/workflows/88/validate" -
Create the mission. Put the workflow's inputs in
attribute_values, keyed by attribute name:curl -s -X POST "$CATALOG/missions" \-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \-d '{"name": "Weekly competitor scan","workflow_id": 88,"phase": "scoping","mission_status": "active","trigger_source": "api","attribute_values": {"region": "APAC"}}'If the workflow takes no inputs, you can use
POST /workflows/88/instantiate?trigger_source=apion the catalog API instead, which creates the mission for you. -
Execute it, using the mission's
id:curl -s -X POST "$AGENT/workflows/execute" \-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \-d '{"workflow_id": 88, "mission_id": 5150, "initial_message": "Run the weekly scan"}'{ "status": "started", "mission_id": 5150, "workflow_id": 88, "message": "Workflow execution started for mission 5150" }To run it in a specific execution environment, add
execution_environment_id. See Execution environments. -
Poll the mission:
curl -s -H "X-API-Key: $FYAI_API_KEY" "$CATALOG/missions/5150" \| jq '{phase, mission_status, percent_completed, current_phase, total_tokens, total_cost}'Field Values phaseexecutingwhile running;completedorfailedwhen finishedmission_statusactive(running),waiting_for_user(paused for an approval) orstoppedpercent_completed0 to 100 current_phaseThe node currently running plan_stepsThe workflow graph. Each node's data.execution_statusanddata.resultPreviewshow its state and output.The run is finished when
phaseiscompletedorfailed, ormission_statusisstopped. You can also watch it under Missions in the web app. -
If the workflow has an approval gate, the mission pauses with
mission_statuswaiting_for_user. List what's waiting and resolve it:curl -s -H "X-API-Key: $FYAI_API_KEY" "$CATALOG/missions/node-approvals/pending"curl -s -X POST "$AGENT/workflows/missions/5150/node-approvals/31/resolve" \-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \-d '{"approved": true}'See Using approval gates.
Start workflows with the X-API-Key header rather than a bearer token. A key lets the platform renew the run's credential, so runs longer than a few minutes don't fail partway.
To trigger workflows from other systems without writing code, use a webhook — see Triggering workflows with webhooks. To run on a timetable, see Scheduling workflows.
Load documents into a knowledge base
-
Create a knowledge base:
curl -s -X POST "$CATALOG/knowledge-bases" \-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \-d '{"name": "Product handbook", "description": "Policies and how-tos"}' -
Add content. Plain text is stored straight away:
curl -s -X POST "$CATALOG/knowledge-documents/ingest-text" \-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \-d '{"knowledge_base_id": 9, "title": "Refund policy", "content": "Customers can request a refund within 30 days…"}'{ "stored_chunks": 3, "total_chunks": 3 }Other sources run in the background and return a
job_id:Endpoint Body POST /knowledge-documents/ingest-urlknowledge_base_id,urlPOST /knowledge-documents/ingest-gitknowledge_base_id,repo_url, optionalbranch(defaultmain),path_filter(default**/*.md),subfolder,integration_idfor private repositories. Needs Write.POST /knowledge-documents/ingest-confluenceknowledge_base_id,integration_id(orbase_url,username,api_token), andspace_keyorparent_page_idPOST /knowledge-documents/ingest-manifestknowledge_base_id,manifest_id(stored straight away)POST /knowledge-documents/uploadMultipart form with knowledge_base_idandfile, up to 50 MBcurl -s -X POST "$CATALOG/knowledge-documents/upload" \-H "X-API-Key: $FYAI_API_KEY" \-F knowledge_base_id=9 -F [email protected] -
Poll a background job:
curl -s -H "X-API-Key: $FYAI_API_KEY" "$CATALOG/knowledge-documents/ingest-jobs/$JOB_ID"statusmoves fromqueuedtodone(withstored_chunks) orerror. Job status is held only briefly; if polling returns404, checkGET /knowledge-documents?knowledge_base_id=9to see whether the documents arrived. -
Search it:
curl -s -X POST "$CATALOG/knowledge-documents/search" \-H "X-API-Key: $FYAI_API_KEY" -H "Content-Type: application/json" \-d '{"knowledge_base_id": 9, "query": "How long do customers have to ask for a refund?", "limit": 5}'Each result has the matching
content, itssource_typeandsource_ref, and ascore.
GET /knowledge-bases/{id}/readiness tells you whether a knowledge base can be searched by meaning yet, and why not if it can't. For how knowledge bases work and how agents use them, see Knowledge bases and Setting up knowledge bases.