# API Documentation
Source: https://docs.xpander.ai/api-reference/index
REST API, Python SDK, and MCP Protocol for building and managing AI agents
Choose your integration method based on your use case:
**Platform REST API**
Universal HTTP endpoints for managing agents, tasks, and knowledge bases from any programming language.
**SDK for Building Agents**
Comprehensive Python library with decorators, event handling, and framework integration for building sophisticated AI agents.
**MCP for Claude & IDEs**
Expose agents and tools as MCP servers for Claude Desktop, Cursor, and other MCP clients.
## Quick Comparison
| Feature | REST API | Python SDK | Model Context Protocol |
| -------------------- | ----------------------------- | ---------------------------- | ----------------------------- |
| **Language Support** | Any language | Python only | Any MCP client |
| **Primary Use Case** | Control plane operations | Building agents | Discovering & invoking agents |
| **Setup Complexity** | Minimal (API key) | pip install | MCP client config |
| **Best For** | CRUD operations, integrations | Agent development, workflows | IDE/AI client integration |
| **Real-time** | Polling or webhooks | Event decorators | Server-Sent Events |
## Getting Started
Sign up at [chat.xpander.ai](https://chat.xpander.ai) and generate your API key from the dashboard
* **REST API**: For universal access from any language
* **Python SDK**: For building agents in Python
* **MCP Protocol**: For IDE and AI client integration
Each integration method has comprehensive documentation, examples, and quick start guides
## REST API - Platform
The REST API provides complete control over your resources:
```bash theme={"dark"}
# List agents
curl -X GET "https://api.xpander.ai/v1/agents" \
-H "x-api-key: YOUR_API_KEY"
# Invoke an agent
curl -X POST "https://api.xpander.ai/v1/agents/{agent_id}/invoke" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input": {"text": "Analyze this data"}}'
```
View complete REST API documentation with all endpoints
## Python SDK - Build Agents
The Python SDK enables rapid agent development with powerful abstractions:
```python theme={"dark"}
from xpander_sdk import Agents, on_task
# Initialize SDK
agents = Agents()
# Define task handler
@on_task
async def handle_task(task):
print(f"Processing: {task.id}")
task.result = "Task completed"
return task
# List and invoke agents
agent = await agents.aget("agent-id")
task = await agent.acreate_task(prompt="Analyze data")
```
View complete SDK documentation with modules and examples
## Model Context Protocol - Expose to Claude & IDEs
Connect your agents and tools to Claude Desktop, Cursor, and other MCP clients:
```json theme={"dark"}
{
"mcpServers": {
"xpander.ai": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"https://api.xpander.ai/mcp/",
"--header",
"x-api-key:YOUR_API_KEY"
]
}
}
}
```
View complete MCP setup guide with examples
## Authentication
All integration methods use API key authentication:
```bash theme={"dark"}
export XPANDER_API_KEY="your-api-key"
```
Get your API key from the [dashboard](https://platform.xpander.ai).
## Common Use Cases
**Use Python SDK** for building agents with complex workflows, tool integrations, and event handling. The SDK provides decorators and lifecycle management for sophisticated agent architectures.
**Use REST API** for integrating xpander into existing applications written in any language. Perfect for microservices, web apps, and mobile applications.
**Use Model Context Protocol** for accessing agents from Claude Desktop, Cursor, VSCode, or any MCP-compatible client. Enables seamless agent discovery and invocation from your development environment.
**Combine all three**: Build agents with the SDK, manage them via REST API, and access them through MCP clients. All methods work together seamlessly.
## API Resources
Browse all REST API endpoints
Explore SDK modules and classes
View code examples and tutorials
Complete platform documentation
## Support & Community
Join our community
Developer discussions
View source code
# Invoke an Agent via API
Source: https://docs.xpander.ai/api-reference/invoke-api
Call any xpander agent using a simple HTTP request with curl or any HTTP client.
## Base URL
```text theme={"dark"}
https://api.xpander.ai/v1/agents/{agent_id}/invoke
```
## Authentication
All requests require an API key passed as a header:
```text theme={"dark"}
x-api-key: YOUR_XPANDER_API_KEY
```
`Authorization: Bearer` is **not** supported. Use `x-api-key` only.
## Request Body
| Field | Type | Required | Description |
| ------------------ | ------ | -------- | --------------------------------------- |
| `input.text` | string | ✅ | The prompt to send to the agent |
| `input.user.id` | string | ✅ | The xpander user ID |
| `input.user.email` | string | ✅ | The user's email address |
| `user_oidc_token` | string | ⬜ | OAuth token for MCP-authenticated tools |
## Examples
### Synchronous Invocation
Waits for the agent to complete and returns the result inline.
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents/{agent_id}/invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_XPANDER_API_KEY" \
-d '{
"input": {
"text": "Your prompt here",
"user": {
"id": "USER_ID",
"email": "user@example.com"
}
}
}'
```
### With MCP OAuth Token
If the agent uses tools that require OAuth (e.g. Notion, Google Calendar), pass the user's OIDC token:
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents/{agent_id}/invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_XPANDER_API_KEY" \
-d '{
"input": {
"text": "Your prompt here",
"user": {
"id": "USER_ID",
"email": "user@example.com"
}
},
"user_oidc_token": "USER_OAUTH_TOKEN"
}'
```
### Asynchronous Invocation
Fire-and-forget — returns immediately with a task ID. Poll for results separately.
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents/{agent_id}/invoke/async" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_XPANDER_API_KEY" \
-d '{
"input": {
"text": "Your prompt here",
"user": {
"id": "USER_ID",
"email": "user@example.com"
}
}
}'
```
## Response
```json theme={"dark"}
{
"id": "task-uuid",
"agent_id": "agent-uuid",
"status": "completed",
"result": "Agent response here",
"source": "api",
"created_at": "2026-04-10T17:34:09.655630Z",
"finished_at": "2026-04-10T17:34:18.685730Z"
}
```
### Status values
| Status | Meaning |
| ----------- | ----------------------------------- |
| `pending` | Task queued |
| `executing` | Agent is running |
| `completed` | Finished successfully |
| `error` | Failed — check `result` for details |
## What NOT to Use
| ❌ Doesn't work | ✅ Use instead |
| ------------------------------------------- | -------------------------------------- |
| `Authorization: Bearer ` | `x-api-key: ` |
| `webhook.xpander.ai` (wraps body as string) | `api.xpander.ai/v1/agents/{id}/invoke` |
| `input.user` with only `id` | Include both `id` and `email` |
# Invoke a Connector via API
Source: https://docs.xpander.ai/api-reference/invoke-connector-api
Find a connector, get its connection, list its operations, and invoke any operation with curl — no agent or task required.
Every connector you set up at [chat.xpander.ai/connectors](https://chat.xpander.ai/connectors) can be called directly over REST. This page walks the full path end to end: **find the connector → get its `connection_id` → pick an operation → invoke it**.
## Base URL & Authentication
```text theme={"dark"}
https://api.xpander.ai
```
All requests require an API key passed as a header:
```text theme={"dark"}
x-api-key: YOUR_XPANDER_API_KEY
```
Your API key is already scoped to your organization — you do **not** need to pass an organization ID.
## The three IDs you need
| ID | What it is | Where to get it |
| --------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `connector_id` | The connector itself (e.g. Firecrawl) | The URL at `chat.xpander.ai/connectors/{connector_id}`, or [List Tools](/api-reference/v1/tools/list-tools) |
| `connection_id` | Your org's authenticated connection to that connector | The `connections[].id` field in [List Tools](/api-reference/v1/tools/list-tools) |
| `operation_id` | The specific action to run | [List Connector Operations](/api-reference/v1/tools/list-connector-operations) — accepts the operation's `id` **or** its `operationId` |
The connector page URL in the app gives you the `connector_id` — but invoking also requires a `connection_id`, which is a different UUID. Step 1 below shows how to get it.
## Step 1 — Find the connector and its connection
Search your tool catalog by name:
```bash theme={"dark"}
curl "https://api.xpander.ai/v1/tools?type=connector&query=firecrawl" \
-H "x-api-key: YOUR_XPANDER_API_KEY"
```
```json theme={"dark"}
{
"items": [
{
"kind": "connector",
"id": "11111111-2222-3333-4444-555555555555",
"name": "Firecrawl",
"status": "ready",
"total_operations": 6,
"using_built_in_auth": true,
"connections": [
{
"id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"name": "Firecrawl",
"access_scope": "organizational"
}
]
}
],
"total": 1
}
```
Here `items[].id` is the **`connector_id`** and `items[].connections[].id` is the **`connection_id`**.
An empty `connections` array means the connector isn't connected yet — create a connection first with [Connect Connector](/api-reference/v1/tools/connect-connector) (OAuth2 connectors return a `connector_page_url` to finish auth in the browser).
## Step 2 — List the operations
```bash theme={"dark"}
curl "https://api.xpander.ai/v1/tools/connectors/{connector_id}/operations?connection_id={connection_id}" \
-H "x-api-key: YOUR_XPANDER_API_KEY"
```
```json theme={"dark"}
[
{
"id": "67e2daf399f31f9c55d127a7",
"operationId": "FirecrawlScrapingServiceExtractWebpageContent",
"path": "/scrape",
"method": "post",
"pretty_name": "Extract Webpage Content",
"pretty_description": "Extracts content from a specified webpage URL."
}
]
```
Either `id` or `operationId` works as the `operation_id` in the next steps.
## Step 3 (optional) — Inspect the operation's inputs
```bash theme={"dark"}
curl "https://api.xpander.ai/v1/tools/connectors/{connector_id}/connections/{connection_id}/{operation_id}/schema" \
-H "x-api-key: YOUR_XPANDER_API_KEY"
```
The response's `input` field is a JSON schema with three groups — `body_params`, `query_params`, and `path_params` — which is exactly the structure the invoke call accepts.
## Step 4 — Invoke
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/tools/connectors/{connector_id}/connections/{connection_id}/{operation_id}" \
-H "x-api-key: YOUR_XPANDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"body_params": {
"url": "https://example.com",
"formats": ["markdown"]
}
}'
```
The response is the **target API's response**, passed through unchanged:
```json theme={"dark"}
{
"success": true,
"data": {
"markdown": "# Example Domain\n\nThis domain is for use in documentation examples...",
"metadata": {
"title": "Example Domain",
"sourceURL": "https://example.com",
"statusCode": 200
}
}
}
```
### How the request body maps to the target API
| Field | Purpose | Example |
| -------------- | ------------------------------------ | -------------------------------- |
| `body_params` | The JSON body sent to the target API | `{"url": "https://example.com"}` |
| `query_params` | Query-string parameters, by name | `{"limit": 10}` |
| `path_params` | Path parameters, by name | `{"crawlJobId": "abc123"}` |
| `headers` | Extra headers for the target API | `{"Accept": "text/csv"}` |
All four fields are optional — send only what the operation's schema requires. The operation always runs with its spec-defined HTTP method (a GET operation stays a GET), even though you call this endpoint with POST. The connection's stored credentials are applied automatically, and the call times out after 300 seconds.
You can pass `_` as the `connector_id` and it will be resolved from the connection:
`POST /v1/tools/connectors/_/connections/{connection_id}/{operation_id}`
## Common mistakes
| ❌ Doesn't work | ✅ Use instead |
| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Using the connector page URL's UUID as `connection_id` | That UUID is the `connector_id`; get `connection_id` from [List Tools](/api-reference/v1/tools/list-tools) |
| `Authorization: Bearer ` with an API key | `x-api-key: ` |
| Putting the target API's arguments at the top level of the body | Wrap them in `body_params` / `query_params` / `path_params` |
| `GET /v1/tools/search?query=...` without `type` | Always pass `type` as well, e.g. `?query=firecrawl&type=connector` |
# Model Context Protocol
Source: https://docs.xpander.ai/api-reference/mcp
Expose agents and tools as MCP servers for Claude Desktop, Cursor, and other MCP clients
The Model Context Protocol (MCP) integration allows you to expose your agents and tools as MCP servers that can be connected to Claude Desktop, Cursor, VSCode, and any MCP-compatible client.
## Overview
xpander provides three ways to use MCP:
Pick and choose tools from multiple connectors and expose them as a single MCP server
Expose your AI agents as MCP servers that can be invoked from MCP clients
Expose an entire connector (like Slack or GitHub) as an MCP server
## MCP Server Endpoints
Two endpoints are available:
**Standard MCP:**
```
https://api.xpander.ai/mcp/
```
**Server-Sent Events (SSE):**
```
https://api.xpander.ai/mcp/sse
```
Authentication is provided via your API key in the request headers.
OAuth authentication (without API key) is coming soon!
Your API key is a sensitive credential. Never share it publicly or commit it to version control.
## Configuration for Claude Desktop
Add the MCP server to Claude Desktop by editing:
```
~/Library/Application Support/Claude/claude_desktop_config.json
```
Basic configuration format:
```json theme={"dark"}
{
"mcpServers": {
"xpander.ai": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"https://api.xpander.ai/mcp/",
"--header",
"x-api-key:YOUR_API_KEY"
]
}
}
}
```
Replace `YOUR_API_KEY` with your actual API key from [platform.xpander.ai](https://platform.xpander.ai).
## Quick Setup
Get your API key from [platform.xpander.ai](https://platform.xpander.ai)
Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json theme={"dark"}
{
"mcpServers": {
"xpander.ai": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"https://api.xpander.ai/mcp/",
"--header",
"x-api-key:YOUR_API_KEY"
]
}
}
}
```
Restart Claude Desktop to load the new configuration
Ask Claude: "What agents are available?" or "List my tools"
## Available Tools
Once connected, Claude Desktop and other MCP clients can use these tools:
* **List agents** - List all available agents in your organization
* **Invoke agent** - Execute an agent task
* **Create task** - Create a new task for an agent
* **Get task** - Retrieve task details and status
* **Get agent threads** - Get conversation threads for an agent
* **Get thread messages** - Retrieve messages from a specific thread
## Use Case 1: MCP Composition
Create custom MCP servers with specific tools from the xpander console at [chat.xpander.ai](https://chat.xpander.ai):
1. Go to **MCP Servers** → **New MCP Server**
2. Select specific tools from multiple connectors
3. Get a custom MCP URL for that composition
4. Use the same configuration format with the custom URL
## Use Case 2: Agents as MCP
Enable MCP for specific agents:
1. In agent settings, go to **Task Sources** tab
2. Enable the **MCP** toggle
3. Get agent-specific MCP configuration
4. Claude can invoke that specific agent
## Use Case 3: Single Connector
Expose individual connectors (Slack, GitHub, etc.) as MCP servers:
1. Go to **Settings** → **Connectors**
2. Select a connector
3. Click **MCP Configuration**
4. Get connector-specific MCP URL
## Authentication
If you've already authenticated connectors in xpander (Gmail, LinkedIn, Slack, etc.), they work automatically through MCP without additional authentication in Claude.
## Testing Your MCP Integration
After configuration, test by asking Claude:
* "What agents are available?"
* "List my agents"
* "Invoke my data analysis agent to analyze this data"
* "Create a task for my support agent"
* "What's the status of task xyz?"
Claude will use the MCP tools to interact with your agents and tasks.
## Example Configurations
```json theme={"dark"}
{
"mcpServers": {
"xpander.ai": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"https://api.xpander.ai/mcp/",
"--header",
"x-api-key:YOUR_API_KEY"
]
}
}
}
```
```json theme={"dark"}
{
"mcpServers": {
"xpander.ai": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"https://api.xpander.ai/mcp/sse",
"--header",
"x-api-key:YOUR_API_KEY"
]
}
}
}
```
Replace `YOUR_API_KEY` with your own credentials. Never commit API keys to version control.
## Supported MCP Clients
xpander MCP servers work with:
* **Claude Desktop** - Anthropic's desktop application
* **Cursor** - AI-powered code editor
* **VSCode** - With MCP extension
* **Any MCP-compatible client** - Following the Model Context Protocol specification
## Roadmap
**Coming Soon**: OAuth authentication support, allowing you to connect without manually managing API keys.
## Next Steps
Complete MCP setup with screenshots
Manage agents via REST API
Build agents with the SDK
# Platform REST API
Source: https://docs.xpander.ai/api-reference/rest-api
Universal REST API for managing agents, tasks, and knowledge bases
The REST API provides comprehensive HTTP endpoints for managing your AI agents, executing tasks, and controlling knowledge bases from any programming language.
## Overview
The REST API is your control plane for the xpander platform, enabling you to:
* **Manage Agents**: Create, update, deploy, and delete AI agents
* **Agent Workspace**: Run bash commands, edit files, search code, and share artifacts inside a per-agent workspace
* **Manage Workflows**: Build and run multi-agent orchestration workflows
* **Connectors**: Connect to external services, search and manage operations
* **Custom Functions**: Create, generate, and execute user-defined Python tools
* **Export & Import**: Share agents as templates across organizations
* **Execute Tasks**: Invoke agents and workflows synchronously, asynchronously, or with streaming
* **Control Knowledge**: Manage knowledge bases and documents
* **Access Toolkits**: List and invoke tools across integrations
* **LLM Providers**: Discover available LLM providers and models
## Base URL
```
https://api.xpander.ai
```
## Authentication
All API requests require authentication via the `x-api-key` header:
```bash theme={"dark"}
curl -X GET "https://api.xpander.ai/v1/agents" \
-H "x-api-key: YOUR_API_KEY"
```
## Quick Start
```bash cURL theme={"dark"}
# List all agents
curl -X GET "https://api.xpander.ai/v1/agents" \
-H "x-api-key: YOUR_API_KEY"
# Invoke an agent
curl -X POST "https://api.xpander.ai/v1/agents/{agent_id}/invoke" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"text": "Analyze this data"
}
}'
```
```python Python theme={"dark"}
import requests
API_KEY = "your-api-key"
BASE_URL = "https://api.xpander.ai/v1"
# List all agents
response = requests.get(
f"{BASE_URL}/agents",
headers={"x-api-key": API_KEY}
)
agents = response.json()
# Invoke an agent
response = requests.post(
f"{BASE_URL}/agents/{agent_id}/invoke",
headers={"x-api-key": API_KEY},
json={"input": {"text": "Analyze this data"}}
)
result = response.json()
```
```javascript JavaScript theme={"dark"}
const API_KEY = 'your-api-key';
const BASE_URL = 'https://api.xpander.ai/v1';
// List all agents
const agents = await fetch(`${BASE_URL}/agents`, {
headers: { 'x-api-key': API_KEY }
}).then(r => r.json());
// Invoke an agent
const result = await fetch(`${BASE_URL}/agents/${agentId}/invoke`, {
method: 'POST',
headers: {
'x-api-key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
input: { text: 'Analyze this data' }
})
}).then(r => r.json());
```
## API Endpoints
Create, manage, and invoke AI agents
Run commands, edit files, and share artifacts in a per-agent workspace
Build and run multi-agent orchestration workflows
Discover connectors, connect, inspect operation schemas, and invoke operations
Create and execute user-defined Python tools
Monitor and manage task executions
Manage knowledge bases and documents
Discover available LLM providers and models
## Key Features
* **🌐 Universal Access**: Works with any programming language that supports HTTP
* **⚡ Multiple Execution Modes**: Sync, async, and streaming invocation
* **📊 Complete CRUD**: Full lifecycle management for all resources
* **🔒 Secure**: API key authentication with organization-level scoping
* **📖 OpenAPI Spec**: Complete OpenAPI 3.1 specification available
## Response Format
All API responses follow a consistent JSON structure:
```json theme={"dark"}
{
"id": "resource-id",
"status": "completed",
"created_at": "2025-11-05T20:00:00Z",
...
}
```
## Error Handling
The API uses standard HTTP status codes:
* `200` - Success
* `201` - Created
* `400` - Bad Request
* `401` - Unauthorized
* `404` - Not Found
* `422` - Validation Error
* `500` - Internal Server Error
Error responses include detailed information:
```json theme={"dark"}
{
"detail": [
{
"loc": ["body", "input"],
"msg": "field required",
"type": "value_error.missing"
}
]
}
```
## Rate Limits
The API implements rate limiting to ensure fair usage:
* **Standard**: 100 requests per minute
* **Burst**: 1000 requests per hour
Rate limit headers are included in responses:
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1699200000
```
## Next Steps
Explore agent management endpoints
Build multi-agent orchestrations
View code examples
Download OpenAPI specification
# Create Agent
Source: https://docs.xpander.ai/api-reference/v1/agents/create-agent
POST /v1/agents
Create a new AI agent with specified configuration, tools, and knowledge bases
Create a new AI agent with custom configuration. The agent will be created and ready for configuration and deployment.
## Request Body
Display name for the agent
Description of the agent's purpose and capabilities
Deployment infrastructure: `serverless`.
LLM provider: `openai` (default), `anthropic`, etc.
Specific model version (e.g., `gpt-4o`, `gpt-4.1`)
Emoji icon for the agent (e.g., "🚀", "📊")
System instructions configuration
Array of role descriptions for the agent
Array of goal descriptions for the agent
General instructions text
Access control scope for the agent. Determines who can see and use the agent.
Possible values: `personal` (visible only to the creator) or `organizational` (visible to the entire organization). Defaults to `organizational` if not specified.
Target environment ID (optional)
Use Nvidia NeMo (default: false)
Custom API base URL for LLM provider (for AI Gateway configurations)
Custom HTTP headers to include in LLM requests for gateway integration
Reasoning effort level for the LLM (e.g., `low`, `medium`, `high`)
Agent type: `manager` (default), `regular`, `a2a`, `curl`
Output format: `text` (default) or `json`
JSON schema for structured output when `output_format` is `json`
Natural-language description of the desired output
Agent framework (e.g., `agno`)
Array of connector tool attachments with connection IDs and selected operation IDs
Agent workflow graph configuration defining tool execution order
Array of knowledge base IDs to attach to the agent
Advanced agent settings including memory, session storage, tool limits, and safety features
Task-level strategies for retry, stop conditions, and iteration
Notification configuration (Slack, email, webhook) for agent events
Deep planning configuration for complex multi-step tasks
Voice ID for text-to-speech output
Source node configurations (e.g., Slack, web UI triggers)
Whether the agent requires human approval for tool calls
## Response
Returns a complete `AIAgent` object:
Unique identifier for the created agent (UUID)
Display name of the agent
Agent description
Emoji icon representing the agent
Current deployment status: `ACTIVE` or `INACTIVE`
UUID of the organization that owns this agent
Deployment infrastructure: `serverless` or `null`
System instructions configuration
Access control scope: `personal` or `organizational`
AI model provider (e.g., `openai`)
Specific model version (e.g., `gpt-4o`, `gpt-4.1`)
Agent framework used (e.g., `agno`)
Auto-generated human-friendly slug identifier (e.g., "beige-swallow")
Agent version number
Array of tools available to the agent
Array of knowledge bases attached to the agent
Agent workflow graph configuration
Auto-generated webhook URL for agent invocations
## Example Request
Minimal create request (required fields only):
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"name": "Customer Support Agent",
"model_provider": "openai",
"model_name": "gpt-5.2"
}'
```
With full configuration:
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"name": "Customer Support Agent",
"model_provider": "openai",
"model_name": "gpt-5.2",
"instructions": {
"role": ["Customer support specialist"],
"goal": ["Resolve customer issues efficiently"],
"general": "Be helpful, professional, and empathetic"
},
"access_scope": "organizational"
}'
```
## Example Response
```json theme={"dark"}
{
"id": "",
"unique_name": "jade-bass",
"name": "Customer Support Agent",
"description": "",
"deployment_type": "serverless",
"framework": "agno",
"status": "ACTIVE",
"model_provider": "openai",
"model_name": "gpt-5.2",
"organization_id": "",
"version": 2,
"has_pending_changes": false,
"is_latest": false,
"tools": [],
"instructions": {
"role": [],
"goal": [],
"general": ""
},
"access_scope": "organizational",
"knowledge_bases": [],
"icon": "🚀",
"agno_settings": {
"session_storage": true,
"agent_memories": false,
"agentic_culture": false,
"user_memories": false,
"agentic_memory": false,
"session_summaries": false,
"num_history_runs": 10,
"max_tool_calls_from_history": 0,
"tool_call_limit": 0,
"coordinate_mode": true,
"pii_detection_enabled": false,
"pii_detection_mask": true,
"prompt_injection_detection_enabled": false,
"openai_moderation_enabled": false,
"openai_moderation_categories": null,
"reasoning_tools_enabled": true,
"tool_calls_compression": {
"enabled": false,
"threshold": 3,
"instructions": ""
}
},
"webhook_url": "https://webhook.xpander.ai/?agent_id=&asynchronous=false"
}
```
## Notes
* Only `name` is required. All other fields are optional and will use platform defaults.
* The `unique_name` is auto-generated as a human-friendly slug (e.g., "jade-bass")
* The `webhook_url` is auto-generated for agent invocations
* Agent starts in `ACTIVE` status immediately upon creation and is ready for invocation
* `version` starts at 2 and increments with each deployment
* `has_pending_changes` indicates whether there are unpublished configuration changes
* The API may auto-upgrade `model_name` (e.g., requested `gpt-4.1` returns `gpt-5.2`)
## Next Steps
After creating an agent:
1. Update instructions using [Update Agent](/api-reference/v1/agents/update-agent)
2. Add tools and knowledge bases to the agent
3. Deploy the agent using [Deploy Agent](/api-reference/v1/agents/deploy-agent)
4. Invoke the agent using the task execution endpoints
# Delete Agent
Source: https://docs.xpander.ai/api-reference/v1/agents/delete-agent
DELETE /v1/agents/{agent_id}
Permanently delete an AI agent and all associated resources
Permanently delete an agent. This action cannot be undone.
## Path Parameters
Unique identifier of the agent to delete (UUID format)
## Response
Returns HTTP 202 Accepted with body `null` on successful deletion.
## Example Request
```bash theme={"dark"}
curl -X DELETE -H "x-api-key: " \
https://api.xpander.ai/v1/agents/
```
## Example Response
```
HTTP/1.1 202 Accepted
Content-Type: application/json
null
```
The endpoint returns `202 Accepted` to indicate the deletion request has been accepted and will be processed asynchronously.
## Notes
* All running tasks for this agent will be cancelled
* Agent configuration and execution history will be permanently removed
* This action cannot be undone
* Associated knowledge bases and tools are not deleted (they remain in your organization)
* You can also delete agents through the web dashboard at [https://chat.xpander.ai](https://chat.xpander.ai)
* An agent can only be deleted if the `deletable` field is `true` (use [Get Agent](/api-reference/v1/agents/get-agent) to check)
# Deploy Agent
Source: https://docs.xpander.ai/api-reference/v1/agents/deploy-agent
PUT /v1/agents/{agent_id}
Deploy an AI agent to make it active and available for task execution
Deploy an agent to production. This validates the configuration and makes the agent available for invocation.
## Path Parameters
Unique identifier of the agent to deploy (UUID format)
## Response
Returns HTTP 200 with the complete agent object (same structure as [Create Agent](/api-reference/v1/agents/create-agent)).
Key response fields:
* `id`: Agent identifier
* `name`: Agent display name
* `status`: Updated status (`ACTIVE` or `INACTIVE`)
* `deployment_type`: Deployment infrastructure
* `model_provider`: AI model provider
* `model_name`: Specific model version
* `framework`: Agent framework used
* `organization_id`: UUID of the organization that owns this agent
* `description`: Auto-generated from instructions if not previously set
* `has_pending_changes`: Indicates whether there are unpublished changes
* `version`: Current version number of the agent
## Example Request
```bash theme={"dark"}
curl -X PUT -H "x-api-key: " \
https://api.xpander.ai/v1/agents/
```
## Example Response
```json theme={"dark"}
{
"id": "",
"unique_name": "customer-support-agent",
"name": "Customer Support Agent",
"description": "You are a customer support agent...",
"deployment_type": "serverless",
"framework": "agno",
"status": "ACTIVE",
"icon": "🎧",
"model_provider": "anthropic",
"model_name": "claude-sonnet-4-5-20250929",
"organization_id": "",
"version": 2,
"type": "manager",
"has_pending_changes": false,
"instructions": {
"role": [
"Always greet the customer warmly",
"Search the knowledge base before answering",
"Escalate billing issues"
],
"goal": [
"Resolve customer inquiries on first contact",
"Maintain a friendly tone"
],
"general": "You are a customer support agent..."
}
}
```
## Notes
* Agent must have valid instructions and configuration before deployment
* Deployment validates all configurations and dependencies
* Previously deployed version remains active until new deployment succeeds
* Deployment typically completes within seconds
* After deploy, `description` is auto-generated from instructions if not previously set
* `has_pending_changes` returns to `false` after successful deployment
* Check agent status using [List Agents](/api-reference/v1/agents/list-agents) endpoint
* An `ACTIVE` status indicates the agent is ready to handle tasks
# Export Agent
Source: https://docs.xpander.ai/api-reference/v1/agents/export-agent
POST /v1/agents/{agent_id}/export
Export an AI agent as a reusable template with configuration and knowledge bases
Export an agent into a portable template that can be shared across organizations. The template packages all agent components including configuration, tools, sub-agents, and optionally knowledge bases with their documents.
## Path Parameters
The unique identifier (UUID) of the agent to export
## Request Body
Display name for the template
Description of what the template does
Emoji icon for the template (e.g., "🎧", "🚀")
Controls whether knowledge bases and their document files are included in the export
* `true`: Includes all knowledge bases with their documents and files
* `false`: Exports only agent configuration without knowledge bases
## Response
Returns an `AgentTemplate` object:
Unique identifier for the template (UUID)
Template display name
Template description
Emoji icon representing the template
UUID of the organization that created the template
Complete agent configuration
Original agent ID
Agent name
Agent description
Agent instructions (role, goal, general)
Array of custom functions
Array of connected tools
Array of sub-agent definitions
Array of knowledge bases (if with\_knowledge\_bases is true)
## Example Request
```bash theme={"dark"}
curl -X POST -H "x-api-key: " \
-H "Content-Type: application/json" \
-d '{
"name": "Customer Support Agent Template",
"description": "Pre-configured agent for customer support workflows",
"icon": "🎧",
"with_knowledge_bases": true
}' \
https://api.xpander.ai/v1/agents//export
```
## Example Response
```json theme={"dark"}
{
"id": "",
"name": "Customer Support Agent Template",
"description": "Pre-configured agent for customer support workflows",
"icon": "🎧",
"organization_id": "",
"agent_definition": {
"id": "",
"name": "Customer Support Agent",
"description": "Handles customer inquiries and provides support",
"instructions": {
"role": ["Customer support specialist"],
"goal": ["Resolve customer issues efficiently"],
"general": "Be helpful and professional"
},
"custom_functions": [],
"connectors": [
{
"name": "Ticket System",
"type": "api"
}
],
"sub_agents": [],
"knowledge_bases": [
{
"name": "Product Documentation",
"description": "Product guides and FAQs"
}
]
}
}
```
## Use Cases
* **Cross-Organization Sharing**: Share agent templates with other organizations
* **Backup & Version Control**: Create snapshots of agent configurations
* **Standardization**: Distribute pre-built agents across teams
* **Reusability**: Create templates for frequently used agent patterns
## Notes
* **Cross-Organization Sharing**: Templates can be shared across different organizations - the template ID works universally
* **Knowledge Base Size**: When `with_knowledge_bases: true`, the export includes all document content which may result in larger payloads
* **Tool Credentials**: Tool configurations are exported without credentials - recipients will need to provide their own API keys
* **Template Immutability**: Exported templates are snapshots and won't update if the original agent changes
## See Also
* [Import Agent](/api-reference/v1/agents/import-agent) - Create a new agent from a template
* [Create Agent](/api-reference/v1/agents/create-agent) - Create a new agent from scratch
* [Get Agent](/api-reference/v1/agents/get-agent) - Retrieve agent details
# Cancel Queued Message
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/cancel-queued
DELETE /v1/agents/{agent_id}/gateway/conversations/{conversation_id}/queue/{message_id}
Cancel one pending queued message by id.
Removes a single follow-up from the queue using the `message_id` returned by [Send Conversation Message](/api-reference/v1/agents/gateway/send-message).
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the full conversation model.
# Clear Conversation Queue
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/clear-queue
DELETE /v1/agents/{agent_id}/gateway/conversations/{conversation_id}/queue
Cancel every pending queued message for the conversation.
Removes all queued follow-ups. Does not stop a live run; use [Stop Conversation](/api-reference/v1/agents/gateway/stop) for that.
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the full conversation model.
# Drain Conversation Queue
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/drain-stream
POST /v1/agents/{agent_id}/gateway/conversations/{conversation_id}/drain/stream
Drain an idle conversation's queued follow-ups, streaming each turn over SSE.
Opened when a conversation has queued messages but no live run. Streams the same `TaskUpdateEvent` events as invoke. No-op when a live run already owns the drain.
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the full conversation model.
# Edit Message + Re-invoke
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/edit-message
POST /v1/agents/{agent_id}/gateway/conversations/{conversation_id}/edit/{message_id}
Rewrite a prior user message and re-run the gateway (sync).
Trims every entry after the edited message, then re-runs the turn and returns the finalized execution. Preempts any in-flight run on the same conversation. Use the [stream variant](/api-reference/v1/agents/gateway/edit-message-stream) for live events.
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the full conversation model.
# Edit Message + Re-invoke (Stream)
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/edit-message-stream
POST /v1/agents/{agent_id}/gateway/conversations/{conversation_id}/edit/{message_id}/stream
Stream variant of edit + re-invoke.
Same as [Edit Message + Re-invoke](/api-reference/v1/agents/gateway/edit-message) but streams every `TaskUpdateEvent` over SSE instead of returning the finalized execution.
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the full conversation model.
# Get Conversation
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/get-conversation
GET /v1/agents/{agent_id}/gateway/conversations/{conversation_id}
Fetch a conversation's execution, activity thread, usage, and sub-executions.
Returns the parent execution row, the full activity thread, aggregate cost / token usage, and every sub-execution's (execution, activity, usage) triple.
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the full conversation model.
# Agent Gateway
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/overview
The multi-turn conversational surface for talking with an agent over a long-lived conversation.
The **agent gateway** is the conversational execution surface of the platform. It is the same engine the xpander chat app drives, now exposed on the REST API behind your normal API key (`x-api-key`) or OAuth2 JWT.
Where [Invoke Agent](/api-reference/v1/agents/invoke-sync) runs a single one-shot task, the gateway models a **conversation**: a long-lived thread you can send follow-ups to, queue messages against, stop mid-run, edit, and resume from interactive cards.
## Why the gateway
Two properties make the gateway the right surface for a chat-style experience:
* **Fast time-to-first-token (TTFT).** The gateway is a lightweight router. It streams a `connected` event the instant the request lands, then its router LLM acknowledges and starts answering immediately, before any heavy downstream work begins. You get a first token in roughly one network round-trip instead of waiting for a full agent to spin up and run.
* **Effectively unlimited context window.** The router never stuffs the whole conversation into one LLM context. The actual work is delegated to **sub-executions** - each a fresh, bounded agent run - and their results are summarized back into the conversation. Long threads are compacted as they grow, so a conversation can run far longer than any single model's context limit without degrading.
The trade-off versus one-shot [invoke](/api-reference/v1/agents/invoke-sync): the gateway optimizes for an interactive, growing conversation; invoke optimizes for a single self-contained task you call and forget.
## Conversation model
A conversation is identified by a `conversation_id` (the execution id of its first turn). Within a conversation:
* **Run a turn** with [Run Gateway Turn](/api-reference/v1/agents/gateway/run-turn) or its [streaming variant](/api-reference/v1/agents/gateway/run-turn-stream), passing `id` = your `conversation_id` to start or continue the same conversation. The stream path is the fast-first-token entrypoint.
* **Send a follow-up** with [Send Conversation Message](/api-reference/v1/agents/gateway/send-message). While a turn is running, the follow-up is **queued**; when idle, the response tells you to start a fresh turn.
* **Run-state** ([run-state](/api-reference/v1/agents/gateway/run-state)) is a cheap snapshot you poll to decide what to render: is a turn live, how deep is the queue.
* **Drain** ([drain/stream](/api-reference/v1/agents/gateway/drain-stream)) runs the queued follow-ups for an idle conversation, streaming each turn.
* **Stop** ([stop](/api-reference/v1/agents/gateway/stop)) cancels the active run; the queue survives unless you clear it.
* **Edit** ([edit](/api-reference/v1/agents/gateway/edit-message)) rewrites a prior user message, trims the tail, and re-runs the turn.
* **Answer** ([answers](/api-reference/v1/agents/gateway/submit-answers)) resumes a turn that paused on an `ask_user_questions` card.
## How it works: the gateway is a router
The agent you talk to through the gateway is a **router**. When you send a message, the gateway's own LLM decides what to do with it: answer inline, ask you a clarifying question, or dispatch the actual work to the **downstream agent** as a separate execution (a **sub-execution**).
```mermaid theme={"dark"}
flowchart LR
U([You]) -- message --> C[Conversation
parent execution
conversation_id]
C -- router LLM decides --> C
C -- answer inline --> U
C -- sync sub-execution --> S[Downstream agent]
C -- async sub-execution --> A[Downstream agent]
S -- events stream to root --> C
A -. result pushed to root when done .-> C
```
So one conversation (the **parent execution**, keyed by `conversation_id` = "root") can spawn many **sub-executions**, one per task the router dispatches. Each sub-execution is a full agent run with its own id, status, result, and token usage.
### Sub-executions: sync vs async
The router picks a mode per task:
* **Sync (foreground).** The router drives the downstream agent inline and **streams its events onto the root conversation** as they happen, so you see the child's `tool_call_*`, `chunk`, and `sub_task_finished` events live on the same SSE. The router waits for the child before continuing the turn.
* **Async (background).** The router dispatches the task and keeps going without waiting. You get the **sub-execution id** back immediately, so you can query it on its own with [Get Task](/api-reference/v1/tasks/get-task). When it finishes, its **result is pushed to the root** conversation (a `sub_task_finished` event on a live stream, and it appears under the conversation's `sub_executions` on the next [Get Conversation](/api-reference/v1/agents/gateway/get-conversation)).
The parent execution tracks its children in `sub_executions` (in-flight) and `finished_sub_executions` (done). Either way the root conversation is the single place that accumulates every result.
You can override the router's per-task pick with the `sub_tasks` query parameter on [Run Gateway Turn](/api-reference/v1/agents/gateway/run-turn) and its [streaming variant](/api-reference/v1/agents/gateway/run-turn-stream): `sync` forces every sub-execution to run in the foreground, `async` forces every sub-execution to the background, and `auto` returns the conversation to the computed per-task decision. The mode sticks to the conversation until you pass a different value.
## Sending messages while a turn runs (the queue)
A conversation runs **one turn at a time**. If you send a follow-up while a turn is still running, it does not interrupt or run in parallel - it goes into the conversation's **queue** and runs as the next turn once the current one finishes.
[Send Conversation Message](/api-reference/v1/agents/gateway/send-message) takes a `mode`:
* `mode=auto` (default): queue the message if a turn is running; if the conversation is idle, the response is `started`, meaning you should run the turn yourself with [Run Gateway Turn](/api-reference/v1/agents/gateway/run-turn-stream) (`id` = `conversation_id`).
* `mode=queue`: always enqueue, even if idle.
The response is `{ action, message_id, queue_depth }` - `queued` with the new depth, or `started` when idle.
```mermaid theme={"dark"}
sequenceDiagram
participant C as Client
participant Conv as Conversation (root)
C->>Conv: invoke (id = conversation_id), SSE open, turn running
C->>Conv: POST /messages (follow-up while running)
Conv-->>C: 200 { action: "queued", queue_depth: 1 }
Note over Conv: current turn finishes
Conv-->>C: gateway_queue_updated (drain) then the next turn's events
Note over Conv: drains the queue in order until empty
```
How queued messages actually run:
* If a **live stream** is attached (the turn that was running has an open SSE), it drains the queue itself: when the turn finishes it pops the next message and runs it as the following turn on the **same** stream. Each drain is announced with a `gateway_queue_updated` event (`last_action: "drain"`).
* If **nothing** is holding a stream (you queued over plain REST then disconnected, or queued while idle), call [Drain Queue](/api-reference/v1/agents/gateway/drain-stream) to run the pending messages and stream them. A background reaper is the backstop: it resumes a conversation whose queue is non-empty but has no live run.
Manage the queue with [Run State](/api-reference/v1/agents/gateway/run-state) (current `queue_depth` + previews), [Cancel Queued Message](/api-reference/v1/agents/gateway/cancel-queued) (drop one), and [Clear Queue](/api-reference/v1/agents/gateway/clear-queue) (drop all). [Stop](/api-reference/v1/agents/gateway/stop) cancels the running turn and, by default, keeps the queue.
## Getting results
There are three ways to read what an agent produced, depending on how you called it:
1. **From the stream.** On any streaming endpoint, the terminal `task_finished` event carries the finalized execution, including its `result`. Foreground sub-task results also arrive on the stream as `sub_task_finished` events.
2. **Poll the conversation.** Call [Get Conversation](/api-reference/v1/agents/gateway/get-conversation) at any time. It returns the parent execution (with `status` and `result`), the full activity thread, aggregate token usage, and **every sub-execution's own `(execution, activity, usage)` triple** - so a single call gives you the downstream agents' results too.
3. **Poll the task directly.** Every execution id (the `conversation_id` and each sub-execution id) is a task. Use [Get Task](/api-reference/v1/tasks/get-task) to fetch one execution's status + result, or [Get Task Thread](/api-reference/v1/tasks/get-thread) for its activity log.
### Without holding a stream
For a request/response integration that doesn't keep an SSE open:
1. Run the turn with [Run Gateway Turn](/api-reference/v1/agents/gateway/run-turn) (sync). It blocks until the turn completes and returns the execution with its `result`.
2. Add follow-ups with [Send Conversation Message](/api-reference/v1/agents/gateway/send-message) using `mode=queue`, then run them with [Drain Queue](/api-reference/v1/agents/gateway/drain-stream) (a background reaper also picks up an orphaned queue).
3. Check progress any time with [Run State](/api-reference/v1/agents/gateway/run-state) (`is_running`, `queue_depth`) or [Get Task](/api-reference/v1/tasks/get-task) on the `conversation_id` (status `completed` / `failed` / `stopped`), and read results with [Get Conversation](/api-reference/v1/agents/gateway/get-conversation) (parent `result` plus each sub-execution's `result`).
## Streaming
The streaming endpoints ([run a turn](/api-reference/v1/agents/gateway/run-turn-stream), drain, answers, edit-stream) return **Server-Sent Events**. The stream opens with a `connected` event (fast first byte), then each `data:` line is a JSON `TaskUpdateEvent` (`task_created`, `chunk`, `tool_call_request`, `sub_task_created`, `sub_task_finished`, `task_finished`, and so on) - the same event shape as [Invoke Agent (Stream)](/api-reference/v1/agents/invoke-stream).
## Auth and identity
Every route is agent-scoped and authorized by your API key's access to that agent, exactly like the rest of the v1 API. There is no end-user session, so message and answer bodies accept an optional `user` object if you want to attribute the turn to a specific person; if you omit it, the turn runs without an attributed end-user (continuations keep whatever user the conversation already carries).
# Conversation Run State
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/run-state
GET /v1/agents/{agent_id}/gateway/conversations/{conversation_id}/run-state
Cheap snapshot of a conversation's run and queue state.
Poll this to see whether a turn is live and how many follow-ups are queued (with previews). It is Redis-backed and cheap, so it is safe to poll frequently.
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the full conversation model.
# Run Gateway Turn
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/run-turn
POST /v1/agents/{agent_id}/gateway/invoke
Run a gateway turn and wait for the finalized execution.
Run a turn through the gateway and block until it finishes, returning the completed execution with its `result`.
Pass `id` = your `conversation_id` to start or continue a conversation; omit it to start a new one (the returned execution's id becomes the `conversation_id`). Re-invoking a conversation that is already running preempts the in-flight turn.
Use the `sub_tasks` query parameter to force how the router dispatches downstream work: `sync` runs every sub-execution in the foreground (the turn waits for each child, like the email trigger), `async` pushes every sub-execution to the background (results are pushed back to the conversation later), and `auto` restores the computed per-task decision. This is separate from whether this API call blocks, and the mode sticks to the conversation until changed.
For fast time-to-first-token and live progress, prefer the [streaming variant](/api-reference/v1/agents/gateway/run-turn-stream).
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the full conversation model.
# Run Gateway Turn (Stream)
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/run-turn-stream
POST /v1/agents/{agent_id}/gateway/invoke/stream
Run a gateway turn and stream every event over SSE.
Run a turn through the gateway and stream every `TaskUpdateEvent` over Server-Sent Events. This is the fast-time-to-first-token path: a `connected` event flushes immediately, then the router starts answering before any heavy downstream work begins.
Pass `id` = your `conversation_id` to start or continue a conversation; omit it to start a new one. Sub-execution events (the downstream agents the router dispatches) are forwarded onto the same stream.
Use the `sub_tasks` query parameter to force how the router dispatches downstream work: `sync` runs every sub-execution in the foreground (the turn waits for each child, like the email trigger), `async` pushes every sub-execution to the background (results are pushed back to the conversation later), and `auto` restores the computed per-task decision. This is separate from whether this API call blocks, and the mode sticks to the conversation until changed.
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the event model and how sub-executions stream back.
# Send Conversation Message
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/send-message
POST /v1/agents/{agent_id}/gateway/conversations/{conversation_id}/messages
Send a follow-up to a (possibly running) conversation.
`mode=auto` queues the message while a turn is running and signals `started` when the conversation is idle; `mode=queue` always enqueues.
A `started` response means the message was **not** enqueued (`queue_depth: 0`) - the conversation is idle, so run the turn yourself with [Run Gateway Turn](/api-reference/v1/agents/gateway/run-turn) passing `id` = `conversation_id`. A `queued` response means it was enqueued behind a running turn; that turn drains it automatically, or if nothing is streaming you run the queue with [Drain Queue](/api-reference/v1/agents/gateway/drain-stream).
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the full conversation model.
# Stop Conversation
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/stop
POST /v1/agents/{agent_id}/gateway/conversations/{conversation_id}/stop
Cancel the active run for a conversation.
Cancels the in-flight turn (router plus any child sub-execution). The queue is kept unless `clear_queue=true`.
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the full conversation model.
# Submit Question Answers
Source: https://docs.xpander.ai/api-reference/v1/agents/gateway/submit-answers
POST /v1/agents/{agent_id}/gateway/conversations/{conversation_id}/answers
Answer a prior ask_user_questions card and resume the turn (SSE).
When a turn pauses with an `ask_user_questions` card, submit the structured answers here to resume. Answers are validated against the asked questions; a mismatch returns `400` before any run. Streams the resumed turn's events over SSE.
See the [Agent Gateway overview](/api-reference/v1/agents/gateway/overview) for the full conversation model.
# Get Agent
Source: https://docs.xpander.ai/api-reference/v1/agents/get-agent
GET /v1/agents/{agent_id}
Retrieve an agent in a simplified view — its attached tools as one flat list, plus core configuration.
Returns a **simplified agent view**. Instead of the low-level `graph`, `attached_tools`, `oas`, and fully-resolved tool schemas, the agent's tools are surfaced as one flat `tools` array (see the `AgentTool` shape below). Use the [Tools API](/api-reference/v1/tools/list-tools) to add or remove tools.
## Path Parameters
Unique identifier of the agent (UUID format)
## Response
Agent UUID
Display name
What the agent does (auto-generated on deploy from `instructions`)
Emoji icon (e.g., `🚀`)
Agent type (e.g., `regular`, `manager`)
`ACTIVE` (deployed) or `INACTIVE`
LLM provider (e.g., `anthropic`)
LLM model (e.g., `claude-sonnet-4-6`)
Role statements
Goals
Free-form general instructions
IDs of attached knowledge bases
Trigger source types (e.g., `sdk`, `webhook`, `slack`)
The agent's attached tools, unified across kinds. Each item is an `AgentTool`:
Stable handle for this attached tool. Pass it to [Remove Agent Tool](/api-reference/v1/agents/tools/remove-agent-tool).
One of `action`, `custom_function`, `mcp`, `agent`, `workflow`.
Human-readable tool name.
Connector connection id. `action` only.
Operation catalog id. `action` only.
OpenAPI operationId. `action` only.
Custom function id. `custom_function` only.
MCP registry id. `mcp` only.
Subset of MCP tools exposed. `mcp` only.
Referenced sub-agent or workflow id. `agent` / `workflow` only.
ISO 8601 creation timestamp
UUID of the creating user
Resolved creator details (`null` when unavailable — null-check before reading).
User UUID
Display name (falls back to email/id)
User email
# Get Agent Inbox
Source: https://docs.xpander.ai/api-reference/v1/agents/get-agent-inbox
GET /v1/agents/{agent_id}/inbox
List the conversations that reached an agent by email or WhatsApp
Agents can be reached on inbound channels: email (when an email trigger is configured) and WhatsApp (on a user's personal Omni). This endpoint lists those conversations - the agent's inbox - newest first, with filters for channel, date range and title text.
It is agent-wide: every sender's conversation with this agent, not just the caller's. For an agent's full task history across all sources, use [Get Agent Tasks](/api-reference/v1/agents/get-agent-tasks) instead.
## Path Parameters
Unique identifier of the agent (UUID format)
## Query Parameters
Comma-separated channels to include: `email`, `whatsapp`. Defaults to every channel enabled on the agent. Asking for a channel the agent does not have returns `400`.
Only conversations created at or after this ISO date/datetime. A bare date (`2026-08-01`) covers that whole UTC day.
Only conversations created at or before this ISO date/datetime. A bare date covers the whole day.
Case-insensitive text matched against conversation titles.
Maximum conversations to return (1-50).
## Response
Inbound conversations, newest first
Conversation (task) id - pass it to [Get Task Thread](/api-reference/v1/tasks/get-thread) to read the messages
Inbound channel: `email` or `whatsapp`
Conversation title
Execution status: `pending`, `executing`, `paused`, `error`, `failed`, `completed`, or `stopped`
Profile id or address of whoever started the conversation (nullable)
Sender email address, resolved from the profile when the row carries an id (nullable)
ISO timestamp of the first message
ISO timestamp of the last update
Inbound channels enabled on this agent. An empty array means the agent has no inbox at all - clients should hide the surface rather than show an empty list.
Number of matching conversations before `limit` was applied
## Example Requests
### Everything in the inbox
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//inbox"
```
### Search one channel
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//inbox?source=email&q=invoice&limit=10"
```
### A date range
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//inbox?from_date=2026-08-01&to_date=2026-08-03"
```
## Example Response
```json theme={"dark"}
{
"items": [
{
"id": "df716857-0c93-4ec9-9b91-bbe1b9879b59",
"source": "email",
"title": "Invoice question",
"status": "completed",
"user_id": "92310d0c-feda-4e8d-82df-a5320247b10b",
"sender": "dan@acme.com",
"created_at": "2026-08-03T07:41:12.426253Z",
"updated_at": "2026-08-03T07:41:44.108221Z"
}
],
"sources_enabled": ["email"],
"total": 1
}
```
## Use Cases
* **Inbox view**: render everything people sent an agent, across channels
* **Lookup**: find the conversation a specific person or subject started
* **Triage**: filter by date range to review what arrived while nobody was watching
## Notes
* Only top-level conversations are listed; sub-tasks spawned inside a conversation are excluded
* Each channel is queried separately and the results merged, so a channel that is temporarily unavailable degrades the list rather than failing it - the request only errors when every requested channel fails
* `sender` is null when the conversation came from an identity with no email on file
* The agent itself can list the same conversations in chat, so "what emails did you get?" is answered from real data rather than guessed
## See Also
* [Get Agent Tasks](/api-reference/v1/agents/get-agent-tasks) - all tasks for an agent, any source
* [Get Task Thread](/api-reference/v1/tasks/get-thread) - the messages inside one conversation
* [List Tasks](/api-reference/v1/tasks/list-tasks) - tasks across all agents
# Get Agent Tasks
Source: https://docs.xpander.ai/api-reference/v1/agents/get-agent-tasks
GET /v1/agents/{agent_id}/tasks
Retrieve paginated list of task executions for a specific agent with optional filters
Get paginated task records for a specific agent with support for filtering by user, status, and parent task relationships. In multi-turn conversations, reusing an invocation `id` updates the same task/thread record instead of creating a brand-new top-level item for every turn.
## Path Parameters
Unique identifier of the agent (UUID format)
## Query Parameters
Page number (starting from 1)
Items per page (maximum 50)
Filter by user ID who created the task
Filter by parent task ID (for sub-tasks)
Filter by triggering agent ID (parent calling agent in multi-agent workflows)
Filter by task execution status: `pending`, `executing`, `paused`, `error`, `failed`, `completed`, `stopped`
Filter by internal task processing status
## Response
Array of task objects
Unique identifier for the task (UUID format)
ID of the agent that executed this task
ID of the user who created the task (nullable)
ID of parent task if this is a subtask (nullable)
ID of agent that triggered this task (nullable)
Organization UUID this task belongs to
Current task status: `pending`, `executing`, `paused`, `error`, `failed`, `completed`, or `stopped`
Source of task invocation: sdk, webhook, assistant, etc.
ISO timestamp of task creation
ISO timestamp of last update
Task title or the latest input text for that task/thread
Latest result for that task/thread (nullable, present when completed)
Total number of tasks for this agent
Current page number
Number of items per page
Total number of pages available
## Example Requests
### List all tasks for an agent
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//tasks?page=1&per_page=2"
```
### Filter by status
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//tasks?status=completed&page=1&per_page=10"
```
### Filter by user
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//tasks?user_id=&page=1&per_page=10"
```
## Example Response
```json theme={"dark"}
{
"items": [
{
"id": "fbd08e4d-cfa7-4838-b6e6-e51855ac2ba3",
"agent_id": "",
"user_id": null,
"parent_task_id": null,
"triggering_agent_id": null,
"organization_id": "",
"status": "completed",
"source_node_type": "sdk",
"created_at": "2026-03-23T00:45:24.296117Z",
"updated_at": "2026-03-23T00:45:31.040146Z",
"title": "Reply with exactly SECOND",
"result": "SECOND"
}
],
"total": 6,
"page": 1,
"per_page": 5,
"total_pages": 2
}
```
## Use Cases
* **Monitor Agent Activity**: Track all tasks executed by a specific agent
* **Debug Workflows**: Filter by parent\_task\_id to see sub-task hierarchies
* **User Analytics**: Filter by user\_id to see tasks from specific users
* **Multi-Agent Debugging**: Use triggering\_agent\_id to trace agent-to-agent delegations
* **Performance Analysis**: Track task completion times and status distribution
## Notes
* Tasks are returned in reverse chronological order (newest first)
* Continuing a conversation by sending the same invocation `id` updates the same task/thread record instead of creating a new top-level task item
* The `title`, `result`, and `updated_at` fields reflect the latest turn for that task/thread
* The `source_node_type` indicates how the task was invoked (SDK, webhook, web UI, etc.)
* Sub-tasks (when `parent_task_id` is set) represent work delegated to other agents
* Use [Get Task](/api-reference/v1/tasks/get-task) for the latest full task object and [Get Task Thread](/api-reference/v1/tasks/get-thread) or [Get Task Thread (Full)](/api-reference/v1/tasks/get-thread-full) for message history
## See Also
* [List Tasks](/api-reference/v1/tasks/list-tasks) - List all tasks across all agents
* [Get Task](/api-reference/v1/tasks/get-task) - Get detailed information about a specific task
* [Invoke Agent](/api-reference/v1/agents/invoke-async) - Create new tasks
# Import Agent
Source: https://docs.xpander.ai/api-reference/v1/agents/import-agent
POST /v1/agents/template_import/{template_id}
Import an AI agent from a template and create a new agent instance
Create a new agent instance from a template. The template can be from your organization or shared from another organization. All agent configuration, tools, sub-agents, and optionally knowledge bases will be replicated into your organization.
## Path Parameters
Unique identifier of the template to import (UUID format)
## Request Body
Display name for the new agent instance
Description of the agent instance (optional - can customize the template description)
Emoji icon for the agent (optional - defaults to template icon)
Controls whether to import knowledge bases from the template
* `true`: Imports all knowledge bases with their documents and files (if included in template)
* `false`: Imports only agent configuration without knowledge bases
## Response
Returns a complete `AIAgent` object:
Unique identifier for the created agent (UUID)
Display name of the agent
Agent description
Emoji icon representing the agent
Current deployment status: `ACTIVE` or `INACTIVE`
UUID of the template this agent was imported from
Deployment infrastructure: `serverless`
UUID of your organization
System instructions configuration inherited from template
Array of role descriptions
Array of goal descriptions
General instructions text
AI model provider (e.g., `openai`)
Specific model version (e.g., `gpt-4o`, `gpt-4.1`)
Agent framework used (e.g., `agno`)
Array of imported knowledge bases (if `with_knowledge_bases: true`)
ISO 8601 timestamp of when the agent was created
## Example Requests
### Basic Import
```bash theme={"dark"}
curl -X POST -H "x-api-key: " \
-H "Content-Type: application/json" \
-d '{
"name": "My Support Agent",
"description": "Customer support agent from template",
"icon": "🎧",
"with_knowledge_bases": true
}' \
https://api.xpander.ai/v1/agents/template_import/
```
### Import Without Knowledge Bases
```bash theme={"dark"}
curl -X POST -H "x-api-key: " \
-H "Content-Type: application/json" \
-d '{
"name": "Support Agent Framework",
"description": "Will add custom knowledge bases later",
"with_knowledge_bases": false
}' \
https://api.xpander.ai/v1/agents/template_import/
```
## Example Response
```json theme={"dark"}
{
"id": "",
"name": "My Support Agent",
"description": "Customer support agent from template",
"icon": "🎧",
"status": "ACTIVE",
"origin_template": "",
"organization_id": "",
"deployment_type": "serverless",
"created_at": "2026-02-07T10:30:00.000000Z",
"instructions": {
"role": ["Customer support specialist"],
"goal": ["Resolve customer issues efficiently"],
"general": "Be helpful and professional"
},
"model_provider": "openai",
"model_name": "gpt-4.1",
"framework": "agno",
"knowledge_bases": [
{
"id": "",
"name": "Product Documentation",
"description": "Product guides and FAQs"
}
],
"tools": [],
"graph": []
}
```
## Import Behavior
When importing a template:
1. **New Agent Created**: A completely independent agent instance is created in your organization
2. **Configuration Copied**: All agent settings, instructions, and behavior are replicated
3. **Sub-Agents Recreated**: Complete agent hierarchy is maintained with new instances
4. **Knowledge Bases**: Documents are copied to your organization (if included and `with_knowledge_bases: true`)
5. **Tools & Connectors**: Tool configurations are preserved - you'll need to provide credentials
6. **Independence**: Changes to the imported agent won't affect the source agent or template
## Notes
* **Cross-Organization Support**: Templates can be imported from any organization - share the template ID
* **Customization**: You can modify the agent name, description, and icon during import
* **Tool Setup**: After import, configure credentials for any tools that require authentication
* **Knowledge Bases**: If the template was exported without knowledge bases, `with_knowledge_bases: true` has no effect
* **Origin Tracking**: The `origin_template` field tracks which template was used for import
## Next Steps
After importing an agent:
1. Update agent configuration using [Update Agent](/api-reference/v1/agents/update-agent) if needed
2. Configure tool credentials if the agent uses external tools
3. Deploy the agent using [Deploy Agent](/api-reference/v1/agents/deploy-agent)
4. Test the agent with sample tasks
## See Also
* [Export Agent](/api-reference/v1/agents/export-agent) - Create a template from an existing agent
* [Create Agent](/api-reference/v1/agents/create-agent) - Create a new agent from scratch
* [Update Agent](/api-reference/v1/agents/update-agent) - Customize the imported agent
* [Deploy Agent](/api-reference/v1/agents/deploy-agent) - Deploy the imported agent
# Invoke Agent (Async)
Source: https://docs.xpander.ai/api-reference/v1/agents/invoke-async
POST /v1/agents/{agent_id}/invoke/async
Execute an agent asynchronously. Returns immediately with a task ID for polling.
Invoke an agent asynchronously. Returns immediately with a task ID and `status: "pending"`. Poll the [Get Task](/api-reference/v1/tasks/get-task) endpoint to check when results are ready.
Use this for long-running tasks, background processing, or when you don't want to block a request.
## Path Parameters
Agent ID (UUID)
## Request Body
The request body is identical to [Invoke Agent (Sync)](/api-reference/v1/agents/invoke-sync).
* `input.text` is required
* `input.user.id` is required
* `input.user.email` is required
* `user_oidc_token` is optional for MCP OAuth-backed tools
The message or prompt to send to the agent.
End user identity.
External user ID from your system.
User email address.
Optional OIDC token for MCP OAuth-authenticated tools.
Thread ID for multi-turn conversations. Pass the `id` from a previous task to continue the conversation.
When `true`, files in `input.files` are not injected into the LLM context window. See [Invoke Sync: Processing Files](/api-reference/v1/agents/invoke-sync#processing-files).
`default` or `harder`. Controls reasoning depth.
Additional instructions appended to the system prompt for this invocation only.
Extra context appended to the agent's system prompt **for this invocation only**. Unlike `instructions_override` (which adds behavioral instructions), this supplies supplementary facts or context the agent should consider for this run — e.g. relevant background data, the current state of an external system, or a user's recent activity.
Natural-language description of desired output
Per-execution LLM provider override. See [Invoke Sync: Per-Execution LLM Override](/api-reference/v1/agents/invoke-sync#per-execution-llm-override).
Per-execution model override. See [Invoke Sync: Per-Execution LLM Override](/api-reference/v1/agents/invoke-sync#per-execution-llm-override).
Per-execution reasoning-effort override (`low` | `medium` | `high` | `xhigh`). See [Invoke Sync: Per-Execution LLM Override](/api-reference/v1/agents/invoke-sync#per-execution-llm-override).
## Query Parameters
Agent version to invoke. Defaults to latest deployed. Use `"draft"` to test undeployed changes.
## Response
Returns immediately with the task object in `pending` state.
Task ID — use this to poll for results via [Get Task](/api-reference/v1/tasks/get-task)
Always `pending` on initial return. Transitions to `executing` → `completed` (or `failed`/`error`).
`null` until the task completes
## Basic Example
```bash theme={"dark"}
curl -s -X POST "https://api.xpander.ai/v1/agents//invoke/async" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{"input": {"text": "Analyze competitor pricing for Q1 2026"}}'
```
Response (immediate):
```json theme={"dark"}
{
"id": "81250b20-e9d7-4b3b-9995-07dc72b4bb59",
"agent_id": "",
"status": "pending",
"result": null,
"created_at": "2026-02-07T02:13:26.325626Z"
}
```
## Polling for Results
```bash theme={"dark"}
# 1. Start the async task
TASK_ID=$(curl -s -X POST "https://api.xpander.ai/v1/agents//invoke/async" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{"input": {"text": "Generate a market report"}}' | jq -r '.id')
echo "Task started: $TASK_ID"
# 2. Poll until done
while true; do
RESPONSE=$(curl -s "https://api.xpander.ai/v1/tasks/$TASK_ID" \
-H "x-api-key: ")
STATUS=$(echo "$RESPONSE" | jq -r '.status')
echo "Status: $STATUS"
if [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ] || [ "$STATUS" = "error" ]; then
echo "$RESPONSE" | jq -r '.result'
break
fi
sleep 2
done
```
## Example Response (After Completion)
Poll the task after it finishes to get the full result:
```json theme={"dark"}
{
"id": "81250b20-e9d7-4b3b-9995-07dc72b4bb59",
"agent_id": "",
"status": "completed",
"input": {
"text": "Analyze competitor pricing for Q1 2026",
"user": null
},
"result": "Based on my analysis, the three main competitors...",
"created_at": "2026-02-07T02:13:26.325626Z",
"finished_at": "2026-02-07T02:13:41.897000Z",
"source": "api"
}
```
## Task Status Flow
`pending` → `executing` → `completed` | `failed` | `error` | `stopped`
For multi-turn conversations, always wait for a task to reach `completed` before sending the next message with the same `id`. Sending a follow-up while the previous task is still `executing` may cause unexpected behavior.
## See Also
* [Invoke Agent (Sync)](/api-reference/v1/agents/invoke-sync) — blocks until completion (best for quick tasks)
* [Invoke Agent (Stream)](/api-reference/v1/agents/invoke-stream) — real-time SSE stream
* [Get Task](/api-reference/v1/tasks/get-task) — poll for task status and results
* [Webhook documentation](/guides/deploy/webhooks) — get notified when tasks complete instead of polling
# Invoke Agent (Stream)
Source: https://docs.xpander.ai/api-reference/v1/agents/invoke-stream
POST /v1/agents/{agent_id}/invoke/stream
Execute an agent with real-time Server-Sent Events (SSE). Reusing `id` continues the same task/thread.
Invoke an agent with real-time streaming via Server-Sent Events (SSE). Events fire as the agent works, so you can render progress, chunks, tool activity, and the final result in an interactive UI.
## Path Parameters
Agent ID (UUID)
## Request Body
The request body is identical to [Invoke Agent (Sync)](/api-reference/v1/agents/invoke-sync). Only `input.text` is required.
The message or prompt to send to the agent.
URLs of files for the agent to process. For large files, set `disable_attachment_injection: true`.
End user identity. See [Invoke Sync docs](/api-reference/v1/agents/invoke-sync#with-user-identity) for the full `user` object schema.
Task/thread ID for multi-turn conversations. Pass the `id` from a previous task response to continue the same conversation. Continued turns keep using that same ID.
When `true`, files in `input.files` are not injected into the LLM context window. See [Invoke Sync: Processing Files](/api-reference/v1/agents/invoke-sync#processing-files).
`default` or `harder`. Controls reasoning depth.
Additional instructions appended to the system prompt for this invocation only.
Extra context appended to the agent's system prompt **for this invocation only**. Unlike `instructions_override` (which adds behavioral instructions), this supplies supplementary facts or context the agent should consider for this run — e.g. relevant background data, the current state of an external system, or a user's recent activity.
Natural-language description of desired output
Per-execution LLM provider override. See [Invoke Sync: Per-Execution LLM Override](/api-reference/v1/agents/invoke-sync#per-execution-llm-override).
Per-execution model override. See [Invoke Sync: Per-Execution LLM Override](/api-reference/v1/agents/invoke-sync#per-execution-llm-override).
Per-execution reasoning-effort override (`low` | `medium` | `high` | `xhigh`). See [Invoke Sync: Per-Execution LLM Override](/api-reference/v1/agents/invoke-sync#per-execution-llm-override).
## Query Parameters
Agent version to invoke. Defaults to latest deployed. Use `"draft"` to test undeployed changes.
## Response Format
Returns `Content-Type: text/event-stream`. Each SSE line is prefixed with `data: ` and contains a JSON object with this top-level shape:
```json theme={"dark"}
{
"type": "task_created | task_updated | chunk | task_finished | ...",
"task_id": "",
"organization_id": "",
"time": "2026-03-23T00:46:03.782693Z",
"data": {}
}
```
For `chunk` events, `data` is a string fragment. For task lifecycle events, `data` is the task object snapshot at that moment.
If you continue a conversation by sending `id: ""`, the stream keeps emitting that same `task_id`. Use [Get Task](/api-reference/v1/tasks/get-task) for the latest turn state and [Get Task Thread](/api-reference/v1/tasks/get-thread) or [Get Task Thread (Full)](/api-reference/v1/tasks/get-thread-full) for the full message history.
## Event Types
Events are emitted in this order during a typical invocation:
Fired immediately. Contains the task object with `status: "pending"`. This is emitted for both brand-new threads and follow-up turns on an existing task/thread ID.
Fired when the task status changes, usually to `executing`. Contains the updated task object.
Agent's internal reasoning step. Contains the thought process as a string.
Agent's analysis step before tool selection.
Agent is calling a tool. Contains tool name, parameters, and reasoning.
Tool returned a result. Contains the output from the tool.
A piece of the agent's final response. Accumulate these to build the full result.
```json theme={"dark"}
{"type": "chunk", "task_id": "...", "data": "partial response text..."}
```
Task is done. Contains the final task object with `status`, `result`, and `finished_at`.
A sub-agent was triggered (multi-agent workflows).
Deep planning step was updated (when `deep_planning` is enabled on the agent).
MCP connector requires authentication. Contains an auth URL the user must visit.
## Basic Example
```bash theme={"dark"}
curl -s --no-buffer -X POST "https://api.xpander.ai/v1/agents//invoke/stream" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{"input": {"text": "Say hello in 5 words"}}'
```
Use `--no-buffer` (or `-N`) for real-time output.
## Real Event Stream
Here's what the actual SSE output looks like from a live invocation:
```
data: {"type":"task_created","task_id":"81c63a62-96f9-47bf-818c-8a0a3e4b6ec8","organization_id":"","time":"2026-03-23T00:46:03.782693Z","data":{"id":"81c63a62-96f9-47bf-818c-8a0a3e4b6ec8","agent_id":"","input":{"text":"Reply with exactly RAW","files":[]},"status":"pending","source":"api","output_format":"markdown","events_streaming":true}}
data: {"type":"task_updated","task_id":"81c63a62-96f9-47bf-818c-8a0a3e4b6ec8","organization_id":"","time":"2026-03-23T00:46:04.419449Z","data":{"id":"81c63a62-96f9-47bf-818c-8a0a3e4b6ec8","status":"executing",...}}
data: {"type":"chunk","task_id":"81c63a62-96f9-47bf-818c-8a0a3e4b6ec8","organization_id":"","time":"2026-03-23T00:46:06.316302Z","data":"RAW"}
data: {"type":"task_finished","task_id":"81c63a62-96f9-47bf-818c-8a0a3e4b6ec8","organization_id":"","time":"2026-03-23T00:46:06.797966Z","data":{"id":"81c63a62-96f9-47bf-818c-8a0a3e4b6ec8","status":"completed","result":"RAW","finished_at":"2026-03-23T00:46:06.752706Z",...}}
```
## Consuming the Stream (Node.js)
```javascript theme={"dark"}
const response = await fetch(
'https://api.xpander.ai/v1/agents//invoke/stream',
{
method: 'POST',
headers: {
'x-api-key': '',
'Content-Type': 'application/json'
},
body: JSON.stringify({
input: { text: 'Your task here' }
})
}
);
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const lines = decoder.decode(value).split('\n');
for (const line of lines) {
if (!line.startsWith('data: ')) continue;
const event = JSON.parse(line.slice(6));
switch (event.type) {
case 'chunk':
// Stream text to UI as it arrives
process.stdout.write(event.data);
break;
case 'tool_call_request':
console.log(`\n[Tool: ${event.data?.tool_name}]`);
break;
case 'task_finished':
console.log('\n\nDone:', event.data.result);
break;
}
}
}
```
## Consuming the Stream (Python)
```python theme={"dark"}
import requests
import json
response = requests.post(
'https://api.xpander.ai/v1/agents//invoke/stream',
json={'input': {'text': 'Your task here'}},
headers={
'x-api-key': '',
'Content-Type': 'application/json'
},
stream=True
)
for line in response.iter_lines():
if not line:
continue
line = line.decode('utf-8')
if not line.startswith('data: '):
continue
event = json.loads(line[6:])
if event['type'] == 'chunk':
print(event['data'], end='', flush=True)
elif event['type'] == 'tool_call_request':
print(f"\n[Calling tool: {event['data'].get('tool_name', 'unknown')}]")
elif event['type'] == 'task_finished':
print(f"\n\nDone. Status: {event['data']['status']}")
```
## Notes
* Use `curl --no-buffer` or `curl -N` for real-time terminal output
* The stream ends after the `task_finished` event — close the connection at that point
* `chunk` events contain raw text fragments; concatenate them for the full response
* `tool_call_request` and `tool_call_result` events let you show tool usage in your UI
* `think` and `analyze` events show the agent's reasoning (useful for debugging and transparency)
* For multi-turn conversations, wait for `task_finished` before sending the next message with the same `id`
* Reusing `id` continues the same task/thread; it does not mint a new top-level task ID for the follow-up turn
* [Get Task](/api-reference/v1/tasks/get-task) shows the latest turn state for that ID, while [Get Task Thread](/api-reference/v1/tasks/get-thread) and [Get Task Thread (Full)](/api-reference/v1/tasks/get-thread-full) show the accumulated conversation
## See Also
* [Invoke Agent (Sync)](/api-reference/v1/agents/invoke-sync) — blocks until completion
* [Invoke Agent (Async)](/api-reference/v1/agents/invoke-async) — returns task ID for polling
* [Get Thread](/api-reference/v1/tasks/get-thread) — retrieve conversation history after streaming
# Invoke Agent (Sync)
Source: https://docs.xpander.ai/api-reference/v1/agents/invoke-sync
POST /v1/agents/{agent_id}/invoke
Execute an agent and wait for completion. Returns the final result.
Invoke an agent synchronously. The request blocks until the agent finishes (typically 5–30 seconds) and returns the completed task with the result.
For longer-running tasks, use [Invoke Agent (Async)](/api-reference/v1/agents/invoke-async) or [Invoke Agent (Stream)](/api-reference/v1/agents/invoke-stream).
## Path Parameters
Agent ID (UUID)
## Request Body
`input.text`, `input.user.id`, and `input.user.email` are required. `user_oidc_token` is optional for MCP OAuth-backed tools.
The message or prompt to send to the agent.
Identity of the end user invoking the agent.
External user ID from your system.
User email address.
Optional OIDC token for MCP OAuth-authenticated tools.
**Thread ID for multi-turn conversations.** Pass the `id` from a previous task's response to continue the same conversation. The agent will have full context of all prior messages. If omitted, a new thread is created automatically.
When `true`, files passed in `input.files` are **not injected into the LLM context window**. The file URLs are still available to the agent's tools, but the raw content won't be prepended to the prompt.
**Use this when:**
* Files are large (would exceed the model's context limit)
* You want tools to process the files rather than the LLM reading them directly
* You're passing many files and don't need them all in context
**Default (`false`):** file contents are downloaded, extracted, and injected directly into the LLM prompt as context.
Controls the agent's reasoning depth. `default` for standard reasoning, `harder` for deeper chain-of-thought analysis. Use `harder` for complex multi-step tasks that benefit from more deliberate planning.
Additional instructions appended to the agent's system prompt **for this invocation only**. Use this to adjust behavior per-request without changing the agent's configuration — for example, restricting output format, adding constraints, or changing tone.
Extra context appended to the agent's system prompt **for this invocation only**. Unlike `instructions_override` (which adds behavioral instructions), this supplies supplementary facts or context the agent should consider for this run — e.g. relevant background data, the current state of an external system, or a user's recent activity.
Natural-language description of the desired output (e.g., `"A bulleted list of key findings"`). Guides the agent's response style.
**Per-execution LLM provider override.** Use the provider's internal identifier (e.g. `openai`, `anthropic`, `bedrock`) from `GET /v1/misc/llm_providers`. Omit to use the agent's configured provider.
**Per-execution model override.** Must be a valid model under the chosen provider (`GET /v1/misc/llm_providers/{provider_identifier}/models`). Examples: `claude-sonnet-4-6`, `gpt-5`, `gemini-2.0-flash`. Omit to use the agent's configured model.
**Per-execution reasoning-effort override** for reasoning-capable models (e.g. GPT-5). One of `low`, `medium`, `high`, `xhigh`. Omit to use the agent's configured reasoning effort.
## Query Parameters
Agent version to invoke. Defaults to the latest deployed version. Use `"draft"` to test undeployed changes.
## Response
The response is the full task object. The key fields you'll use:
Task/thread ID. Pass this back as `id` in your next request to continue the conversation.
`completed`, `failed`, `error`, or `stopped`
The agent's response. If `output_format` is `json`, this is a JSON string — parse it with `JSON.parse()` or `jq`.
ISO 8601 timestamp when the task was created
ISO 8601 timestamp when the task completed
Effective LLM provider used for this execution. Reflects the per-execution override when supplied, otherwise the agent's configured provider.
Effective model name used for this execution. Reflects the per-execution override when supplied, otherwise the agent's configured model.
Effective reasoning effort used for this execution. One of `low`, `medium`, `high`, `xhigh`. Reflects the per-execution override when supplied, otherwise the agent's configured reasoning effort.
## Simplest Possible Invoke
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents//invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{"input": {"text": "What is xpander.ai?"}}'
```
Extract just the result:
```bash theme={"dark"}
curl -s ... | jq -r '.result'
```
## Multi-Turn Conversation
Pass the `id` from the first response to continue the thread:
```bash theme={"dark"}
# Turn 1
curl -s -X POST "https://api.xpander.ai/v1/agents//invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{"input": {"text": "Hi, my name is David and I work at xpander.ai"}}'
# Response includes: "id": "6525177e-06a1-4063-82fe-37382d2302a5"
# Turn 2 — pass the same id
curl -s -X POST "https://api.xpander.ai/v1/agents//invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"input": {"text": "What is my name and where do I work?"},
"id": "6525177e-06a1-4063-82fe-37382d2302a5"
}'
# Agent responds: "Your name is David and you work at xpander.ai."
```
The agent remembers all previous messages in the thread. Always reuse the same `id` for follow-ups.
## With User Identity
Pass the required user fields so the agent can personalize responses and use identity-aware tools:
```bash theme={"dark"}
curl -s -X POST "https://api.xpander.ai/v1/agents//invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"input": {
"text": "What is my user ID and email?",
"user": {
"id": "user-123",
"email": "david@xpander.ai"
}
}
}'
```
```json theme={"dark"}
{
"status": "completed",
"result": "Your user ID is user-123 and your email is david@xpander.ai."
}
```
The `user` object is visible to the agent as context. Both `id` and `email` are required.
## With MCP OAuth
Pass `user_oidc_token` when the agent uses MCP tools that require OAuth on behalf of the user:
```bash theme={"dark"}
curl -s -X POST "https://api.xpander.ai/v1/agents//invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"input": {
"text": "Create a calendar event for tomorrow at 10am",
"user": {
"id": "user-123",
"email": "david@xpander.ai"
}
},
"user_oidc_token": "USER_OIDC_TOKEN"
}'
```
## Processing Files
Files passed in `input.files` are downloaded and injected directly into the LLM context window by default. This works well for small-to-medium files:
```bash theme={"dark"}
curl -s -X POST "https://api.xpander.ai/v1/agents//invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"input": {
"text": "What is the abstract of this paper?",
"files": ["https://assets.xpanderai.io/static/pdf/bitcoin.pdf"]
}
}'
```
```json theme={"dark"}
{
"status": "completed",
"result": "The abstract describes a peer-to-peer electronic cash system that enables direct online payments without financial institutions, solving the double-spending problem through a distributed network using proof-of-work and cryptographic signatures."
}
```
The 9-page Bitcoin whitepaper (above) processes successfully — its content fits within the model's context window.
### Large Files Fail with Direct Injection
Large files will exceed the model's context limit and return an error:
```bash theme={"dark"}
# This 185-page PDF will fail — too large for the context window
curl -s -X POST "https://api.xpander.ai/v1/agents//invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"input": {
"text": "What year was the Apple Macintosh introduced?",
"files": ["https://assets.xpanderai.io/static/pdf/Introducing_the_Apple_Macintosh_1984.pdf"]
}
}'
```
```json theme={"dark"}
{
"status": "error",
"result": "Error code: 413 - {'error': {'type': 'request_too_large', 'message': 'Request exceeds the maximum size'}}"
}
```
Files are injected into the LLM context by default. Documents over \~100 pages will typically exceed the model's token limit. For large documents, use a [Knowledge Base](/api-reference/v1/knowledge/create-knowledge-base) instead — add the document to a KB, attach it to the agent, and the agent will search it automatically via RAG.
### Disable Context Injection
Set `disable_attachment_injection: true` to pass the file URL to the agent's tools without injecting its content into the LLM prompt:
```bash theme={"dark"}
curl -s -X POST "https://api.xpander.ai/v1/agents//invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"input": {
"text": "Analyze this dataset",
"files": ["https://example.com/data.csv"]
},
"disable_attachment_injection": true
}'
```
With this flag, the file URL is available to the agent's tools but the raw content is not prepended to the prompt. Use this when you want the agent's tools to process the file rather than the LLM reading it directly.
For very large files (185+ pages), even `disable_attachment_injection: true` may not be enough — the file can exceed the HTTP request size limit before reaching the LLM. Use a [Knowledge Base](/api-reference/v1/knowledge/create-knowledge-base) for production workflows with large documents.
## Per-Request Instruction Override
Append instructions for this specific invocation without changing the agent's configuration:
```bash theme={"dark"}
curl -s -X POST "https://api.xpander.ai/v1/agents//invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"input": {"text": "Tell me about xpander pricing"},
"title": "Pricing Inquiry",
"instructions_override": "Always respond in exactly 2 sentences. Never use emojis."
}'
```
```json theme={"dark"}
{
"status": "completed",
"title": "Pricing Inquiry",
"result": "xpander.ai offers two main pricing tiers: a Free plan with 2 serverless agents and 100 AI actions, and an In-House plan at $940/month for up to 10 agents and 200K actions. You can deploy on xpander's managed cloud or your own infrastructure."
}
```
## Per-Execution LLM Override
Override the agent's configured provider, model, or reasoning effort for a single invocation without mutating the agent. Useful for A/B testing models, routing specific requests to a stronger or cheaper model, or dialing up reasoning effort on complex prompts:
```bash theme={"dark"}
curl -s -X POST "https://api.xpander.ai/v1/agents//invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"input": {"text": "Summarize the attached research paper"},
"llm_model_provider": "openai",
"llm_model_name": "gpt-5",
"llm_reasoning_effort": "high"
}'
```
All three fields are optional and independent — supply only the ones you want to override. Omitted fields fall back to the agent's configured values.
The response object includes the **effective** `llm_model_provider`, `llm_model_name`, and `llm_reasoning_effort` that were actually used, so downstream metrics and dashboards correctly attribute the run.
## Structured JSON Output
Request structured output with a JSON Schema:
```bash theme={"dark"}
curl -s -X POST "https://api.xpander.ai/v1/agents//invoke" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{"input": {"text": "Look up Stripe"}}'
```
To configure `output_format` and `output_schema` for structured output, use the [Update Agent](/api-reference/v1/agents/update-agent) endpoint or configure it in the dashboard under the Output tab.
## Example Response
```json theme={"dark"}
{
"id": "6525177e-06a1-4063-82fe-37382d2302a5",
"agent_id": "",
"organization_id": "",
"status": "completed",
"input": {
"text": "What is xpander.ai in one sentence?",
},
"result": "xpander.ai is a full-stack platform for building, deploying, and running autonomous AI agents in production.",
"source": "api",
"think_mode": "default",
"disable_attachment_injection": false,
"created_at": "2026-02-07T10:15:22.100233Z",
"started_at": "2026-02-07T10:15:22.500000Z",
"finished_at": "2026-02-07T10:15:28.997811Z",
"execution_attempts": 1,
"llm_model_provider": "anthropic",
"llm_model_name": "claude-sonnet-4-6",
"llm_reasoning_effort": "medium"
}
```
## See Also
* [Invoke Agent (Async)](/api-reference/v1/agents/invoke-async) — returns immediately with a task ID for polling
* [Invoke Agent (Stream)](/api-reference/v1/agents/invoke-stream) — real-time SSE stream of agent activity
* [Get Thread](/api-reference/v1/tasks/get-thread) — retrieve the full conversation history
* [Webhook documentation](/guides/deploy/webhooks) — trigger agents from external systems via the auto-generated `webhook_url`
# List Agents
Source: https://docs.xpander.ai/api-reference/v1/agents/list-agents
GET /v1/agents
Retrieve a paginated list of agents with core metadata. The response may include additional summary fields beyond ID, name, and status.
Retrieve a paginated list of agents for browsing and selection. Although this is the lighter-weight listing endpoint, the payload typically includes core deployment and model metadata and may include additional summary fields such as instructions or compatibility flags.
This endpoint returns standard agents. Workflows (agents of type `orchestration`) are listed separately by [List Workflows](/api-reference/v1/workflows/list-workflows), so the count here can be lower than the total number of agents in your organization.
## Query Parameters
Page number (starting from 1)
Items per page (maximum 50)
## Response
Returns a paginated list of agent summaries. Treat unknown fields as forward-compatible metadata.
Array of agent objects
Unique identifier for the agent (UUID format)
Display name of the agent
Brief description of the agent's purpose
Emoji icon representing the agent
Current deployment status: ACTIVE, INACTIVE
Organization UUID this agent belongs to
Deployment method: serverless or null
ISO timestamp of when the agent was created
UUID of the user who created the agent
Resolved creator details, one per agent item — no extra request needed. `null` when `created_by` is empty or the user cannot be resolved — null-check before reading sub-fields.
User UUID
Display name — first + last name. Falls back to email, then id, when the name is missing. Not guaranteed to be a real first/last name.
User email
High-level role, goal, and general instructions for the agent (nullable)
LLM provider: openai, anthropic, etc.
Specific model version (e.g., gpt-4o, gpt-4.1)
Agent framework used (e.g., agno)
Agent type: `manager`, `regular`, `a2a`, `curl`, or `orchestration`
Custom LLM base URL when the agent uses a proxied or self-hosted model endpoint (nullable)
Whether the agent has unpublished configuration changes
Total number of agents across all pages
Current page number
Number of items per page
Total number of pages available
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/agents?page=1&per_page=2"
```
## Example Response
```json theme={"dark"}
{
"items": [
{
"id": "",
"name": "Product Specialist",
"description": "Processes queries to provide comprehensive product information",
"icon": "🚀",
"status": "ACTIVE",
"organization_id": "",
"deployment_type": "serverless",
"created_at": "2026-02-05T18:35:04.724091Z",
"created_by": "",
"created_by_details": {
"id": "",
"name": "Jane Doe",
"email": "jane@acme.com"
},
"instructions": {
"role": [
"Answer product questions clearly and accurately"
],
"goal": [
"Help users find the right product quickly"
],
"general": "I am a product specialist focused on concise, accurate answers."
},
"model_provider": "openai",
"model_name": "gpt-5.2",
"framework": "agno",
"type": "manager",
"llm_api_base": null,
"has_pending_changes": false
}
],
"total": 12,
"page": 1,
"per_page": 20,
"total_pages": 1
}
```
## Notes
* `/v1/agents` is the lighter-weight listing endpoint, but the response includes more than just `id`, `name`, and `status`
* Additional fields may appear over time; client code should ignore unknown keys
* The `items` array is sorted by creation date (newest first)
* Use pagination to handle large result sets efficiently
* Status values are: `ACTIVE` (deployed and ready), `INACTIVE` (not deployed)
* See [List Agents (Full Details)](/api-reference/v1/agents/list-agents-full) for complete agent configuration
# List Agents (Full Details)
Source: https://docs.xpander.ai/api-reference/v1/agents/list-agents-full
GET /v1/agents/full
Retrieve a paginated list of AI agents in the simplified view (tools as one flat list, no low-level graph/oas).
Retrieve a paginated list of AI agents. Each item is the **simplified agent view** — core configuration plus a flat `tools` array (see [Get Agent](/api-reference/v1/agents/get-agent) for the per-item field shape, including the `AgentTool` object). Low-level `graph`, `attached_tools`, and `oas` are not included; manage tools via the [Tools API](/api-reference/v1/tools/list-tools).
## Query Parameters
Page number (starting from 1)
Items per page (maximum 50)
## Response
Returns a paginated list of agents with complete details:
Array of complete agent objects
Unique identifier for the agent (UUID format)
URL-safe unique name for the agent
Display name of the agent
Detailed description of the agent's purpose and capabilities
Emoji icon representing the agent
Current deployment status: ACTIVE, INACTIVE
Organization UUID this agent belongs to
Deployment method: serverless or null
Agent framework used (e.g., agno)
Agent type: `manager`, `regular`, `a2a`, `curl`, or `orchestration`
ISO timestamp of when the agent was created
UUID of the user who created the agent
Resolved creator details, one per agent item — no extra request needed. `null` when `created_by` is empty or the user cannot be resolved — null-check before reading sub-fields.
User UUID
Display name — first + last name. Falls back to email, then id, when the name is missing. Not guaranteed to be a real first/last name.
User email
Complete system instructions configuration with role, goal, and general fields
LLM provider: openai, anthropic, etc.
Specific model version (e.g., gpt-4o, gpt-4.1)
Array of tool configurations attached to this agent
Array of knowledge base IDs attached to this agent
Visual graph representation of agent's tool and MCP connections
Access control scope: organizational, team, or private
Total number of agents across all pages
Current page number
Number of items per page
Total number of pages available
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/agents/full?page=1&per_page=2"
```
## Example Response
```json theme={"dark"}
{
"items": [
{
"id": "",
"unique_name": "product-specialist",
"name": "Product Specialist",
"description": "Processes queries to provide comprehensive product information",
"icon": "🚀",
"status": "ACTIVE",
"organization_id": "",
"deployment_type": "serverless",
"framework": "agno",
"type": "manager",
"created_at": "2026-02-05T18:35:04.724091Z",
"created_by": "",
"created_by_details": {
"id": "",
"name": "Jane Doe",
"email": "jane@acme.com"
},
"model_provider": "openai",
"model_name": "gpt-4.1",
"instructions": {
"role": [
"You are a product specialist assistant"
],
"goal": [
"Provide accurate product information to customers"
],
"general": "Be helpful and professional"
},
"tools": [
{
"id": "search-products",
"name": "Search Products",
"method": "get",
"path": "/products/search"
}
],
"knowledge_bases": [],
"graph": [],
"access_scope": "organizational"
}
],
"total": 41,
"page": 1,
"per_page": 2,
"total_pages": 21
}
```
## Notes
* This endpoint returns complete agent configurations, which may be slower than the minimal list endpoint
* Use the minimal list endpoint (`GET /v1/agents`) if you only need basic agent information
* The response is automatically filtered based on your API key's permissions
* Large responses may take longer to retrieve due to nested configurations
## See Also
* [List Agents (Minimal)](/api-reference/v1/agents/list-agents) - Lightweight endpoint for basic agent info
* [Get Agent](/api-reference/v1/agents/get-agent) - Get complete details for a single agent
# Create Scheduled Task
Source: https://docs.xpander.ai/api-reference/v1/agents/scheduled-tasks/create-scheduled-task
POST /v1/agents/{agent_id}/scheduled-tasks
Create a recurring scheduled task (cron + prompt) for an agent.
Create a recurring scheduled task. The change takes effect immediately — the agent runs the given
prompt on every cron match.
## Request Body
Cron expression (5-field crontab, UTC). Example: `0 9 * * *` runs daily at 09:00 UTC.
Instruction the agent runs on each fire.
Optional human-readable label for the task.
Create the task active (default) or paused.
## Example Request
```bash theme={"dark"}
curl -X POST -H "x-api-key: " -H "Content-Type: application/json" \
"https://api.xpander.ai/v1/agents//scheduled-tasks" \
-d '{
"cron": "0 9 * * *",
"prompt": "Summarize yesterday'\''s support tickets and post to #ops.",
"title": "Daily ticket digest"
}'
```
## Example Response
```json theme={"dark"}
{
"id": "",
"title": "Daily ticket digest",
"cron": "0 9 * * *",
"prompt": "Summarize yesterday's support tickets and post to #ops.",
"enabled": true
}
```
# Delete Scheduled Task
Source: https://docs.xpander.ai/api-reference/v1/agents/scheduled-tasks/delete-scheduled-task
DELETE /v1/agents/{agent_id}/scheduled-tasks/{task_id}
Delete a scheduled task by its id.
Permanently remove a scheduled task. To stop a task temporarily without losing its config, use
[Update Scheduled Task](/api-reference/v1/agents/scheduled-tasks/update-scheduled-task) with
`enabled: false` instead.
## Example Request
```bash theme={"dark"}
curl -X DELETE -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//scheduled-tasks/"
```
## Example Response
```json theme={"dark"}
{ "deleted": true }
```
# List Scheduled Tasks
Source: https://docs.xpander.ai/api-reference/v1/agents/scheduled-tasks/list-scheduled-task
GET /v1/agents/{agent_id}/scheduled-tasks
List an agent's recurring scheduled tasks.
Returns the recurring scheduled tasks configured on an agent. A scheduled task runs the agent on a
cron schedule with a fixed prompt.
## Response
Array of scheduled tasks.
Task id — pass it to update, run, or delete the task.
Human-readable label.
Cron expression (5-field crontab, UTC), e.g. `0 9 * * *`.
Instruction the agent runs on each fire.
Whether the task is active. Disabled tasks keep their config but do not fire.
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//scheduled-tasks"
```
## Example Response
```json theme={"dark"}
[
{
"id": "",
"title": "Daily ticket digest",
"cron": "0 9 * * *",
"prompt": "Summarize yesterday's support tickets and post to #ops.",
"enabled": true
}
]
```
# Run Scheduled Task Now
Source: https://docs.xpander.ai/api-reference/v1/agents/scheduled-tasks/run-scheduled-task
POST /v1/agents/{agent_id}/scheduled-tasks/{task_id}/run
Fire a scheduled task immediately, regardless of its cron schedule.
Trigger a scheduled task right away without waiting for its next cron match. Useful for testing a
task or running it on demand. The run is executed asynchronously; inspect it via the agent's
[tasks](/api-reference/v1/agents/get-agent-tasks).
## Example Request
```bash theme={"dark"}
curl -X POST -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//scheduled-tasks//run"
```
## Example Response
```json theme={"dark"}
{
"id": "",
"status": "running"
}
```
# Update Scheduled Task
Source: https://docs.xpander.ai/api-reference/v1/agents/scheduled-tasks/update-scheduled-task
PATCH /v1/agents/{agent_id}/scheduled-tasks/{task_id}
Update a scheduled task's cron, prompt, title, or enabled state.
Update any subset of a scheduled task's fields. Set `enabled: false` to **pause** a task without
losing its config; set `enabled: true` to resume. Changes take effect immediately.
## Request Body
New cron expression (5-field crontab, UTC).
New instruction.
New label.
Pause (`false`) or resume (`true`) without losing config.
## Example Request
```bash theme={"dark"}
# Pause a task
curl -X PATCH -H "x-api-key: " -H "Content-Type: application/json" \
"https://api.xpander.ai/v1/agents//scheduled-tasks/" \
-d '{ "enabled": false }'
```
## Example Response
```json theme={"dark"}
{
"id": "",
"title": "Daily ticket digest",
"cron": "0 9 * * *",
"prompt": "Summarize yesterday's support tickets and post to #ops.",
"enabled": false
}
```
# Cancel Self-Schedule
Source: https://docs.xpander.ai/api-reference/v1/agents/self-schedules/cancel-self-schedule
DELETE /v1/agents/{agent_id}/self-schedules/{schedule_id}
Cancel a pending self-scheduled run by its id.
Cancel a pending self-scheduled run before it fires.
## Example Request
```bash theme={"dark"}
curl -X DELETE -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//self-schedules/"
```
## Example Response
```json theme={"dark"}
{ "status": true }
```
# Get Self-Schedule Settings
Source: https://docs.xpander.ai/api-reference/v1/agents/self-schedules/get-self-schedule-settings
GET /v1/agents/{agent_id}/self-schedules/settings
Read whether the agent may schedule its own future runs, and its per-task cap.
Returns the agent's self-scheduling capability. An agent can only book its own future runs when
`can_self_schedule` is enabled.
## Response
Whether the agent may schedule its own future runs.
Per-task lifetime cap on chained self-schedules (1–1000).
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//self-schedules/settings"
```
## Example Response
```json theme={"dark"}
{
"can_self_schedule": true,
"max_self_schedules": 5
}
```
# List Self-Schedules
Source: https://docs.xpander.ai/api-reference/v1/agents/self-schedules/list-self-schedule
GET /v1/agents/{agent_id}/self-schedules
List an agent's self-scheduled future runs.
Self-schedules are **one-shot future runs an agent books for itself at runtime** (when self-scheduling
is enabled). This endpoint lists them — it does not create them. Optionally filter by status.
## Query Parameters
Filter by status: `scheduled`, `completed`, or `failed`.
## Response
Array of self-schedules.
Self-schedule id — pass it to cancel the run.
Owning agent id.
Execution thread the run continues, if any.
Instruction for the scheduled run.
When the run fires (ISO-8601 UTC).
`scheduled`, `completed`, or `failed`.
Creation timestamp.
Last update timestamp.
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/agents//self-schedules?status=scheduled"
```
## Example Response
```json theme={"dark"}
[
{
"id": "",
"agent_id": "",
"task_id": "",
"prompt": "Follow up on the open incident.",
"run_at": "2026-07-01T09:00:00Z",
"status": "scheduled",
"created_at": "2026-06-30T09:00:00Z",
"updated_at": "2026-06-30T09:00:00Z"
}
]
```
# Set Self-Schedule Settings
Source: https://docs.xpander.ai/api-reference/v1/agents/self-schedules/set-self-schedule-settings
PUT /v1/agents/{agent_id}/self-schedules/settings
Enable or disable the agent's self-scheduling capability and its per-task cap.
Enable or disable whether the agent can schedule its own future runs, and optionally set the per-task
cap on chained self-schedules.
## Request Body
Whether the agent may schedule its own future runs.
Per-task lifetime cap on chained self-schedules. Must be between 1 and 1000.
## Example Request
```bash theme={"dark"}
curl -X PUT -H "x-api-key: " -H "Content-Type: application/json" \
"https://api.xpander.ai/v1/agents//self-schedules/settings" \
-d '{ "can_self_schedule": true, "max_self_schedules": 5 }'
```
## Example Response
```json theme={"dark"}
{
"can_self_schedule": true,
"max_self_schedules": 5
}
```
# Add Agent Tool
Source: https://docs.xpander.ai/api-reference/v1/agents/tools/add-agent-tool
POST /v1/agents/{agent_id}/tools
Attach a tool to an agent (action, custom_function, mcp, agent, or workflow). The API handles catalog resolution and graph wiring.
The request body is discriminated by `type`:
* `action` — `{ "type": "action", "connection_id": "...", "operation_ids": [""] }`
* `custom_function` — `{ "type": "custom_function", "custom_function_id": "..." }`
* `mcp` (registry) — `{ "type": "mcp", "mcp_id": "" }`
* `mcp` (inline) — `{ "type": "mcp", "url": "https://...", "name": "...", "transport": "streamable-http" }`
* `agent` (sub-agent) — `{ "type": "agent", "agent_id": "..." }`
* `workflow` — `{ "type": "workflow", "workflow_id": "..." }`
# List Agent Tools
Source: https://docs.xpander.ai/api-reference/v1/agents/tools/list-agent-tools
GET /v1/agents/{agent_id}/tools
List the tools attached to an agent in a simple, unified shape.
# Remove Agent Tool
Source: https://docs.xpander.ai/api-reference/v1/agents/tools/remove-agent-tool
DELETE /v1/agents/{agent_id}/tools/{tool_id}
Remove a tool from an agent by its tool id (the id returned by List Agent Tools).
# Update Agent
Source: https://docs.xpander.ai/api-reference/v1/agents/update-agent
PATCH /v1/agents/{agent_id}
Update an existing AI agent's configuration, tools, or knowledge bases
Modify an agent's configuration. Only provided fields will be updated. At least one field must be provided.
To add or remove **tools** (connector actions, custom functions, MCP servers, sub-agents, workflows), prefer the dedicated agent tools endpoints — [List](/api-reference/v1/agents/tools/list-agent-tools) / [Add](/api-reference/v1/agents/tools/add-agent-tool) / [Remove](/api-reference/v1/agents/tools/remove-agent-tool). They handle catalog resolution and graph wiring for you, instead of hand-editing low-level `graph`/`attached_tools`.
## Path Parameters
Unique identifier of the agent to update (UUID format)
## Query Parameters
Automatically deploy the agent after updating to apply changes immediately. Without this, changes are staged but not active until a separate PUT deploy call.
## Request Body
Display name for the agent
Description of the agent's purpose and capabilities
System instructions configuration
Array of role descriptions
Array of goal descriptions
General instructions text
Emoji icon representing the agent
AI model provider (e.g., `openai`)
Specific model version (e.g., `gpt-4o`, `gpt-4.1`)
Agent status (enum: `ACTIVE`, `INACTIVE`)
Custom API base URL for LLM provider (for AI Gateway configurations)
Custom HTTP headers to include in LLM requests for gateway integration
Reasoning effort level for the LLM (e.g., `low`, `medium`, `high`)
Output format: `text` or `json`
JSON schema for structured output when `output_format` is `json`
Natural-language description of the desired output
Target environment ID
Access control scope: `personal` or `organizational`
Agent type: `manager`, `regular`, `a2a`, `curl`
Array of connector tool attachments with connection IDs and selected operation IDs
Agent workflow graph configuration defining tool execution order
Array of knowledge base IDs to attach to the agent
Advanced agent settings including memory, session storage, tool limits, and safety features
Task-level strategies for retry, stop conditions, and iteration
Notification configuration (Slack, email, webhook) for agent events
Deep planning configuration for complex multi-step tasks
Voice ID for text-to-speech output
Source node configurations (e.g., Slack, web UI triggers)
Whether the agent requires human approval for tool calls
## Response
Returns the updated `AIAgent` object with all current configuration.
## Example Request
```bash theme={"dark"}
curl -X PATCH -H "x-api-key: " \
-H "Content-Type: application/json" \
-d '{
"name": "Customer Support Agent",
"model_provider": "anthropic",
"model_name": "claude-sonnet-4-5-20250929",
"instructions": {
"role": [
"Always greet the customer warmly",
"Search the knowledge base before answering",
"Escalate billing issues"
],
"goal": [
"Resolve customer inquiries on first contact",
"Maintain a friendly tone"
],
"general": "You are a customer support agent..."
},
"access_scope": "personal"
}' \
https://api.xpander.ai/v1/agents/
```
## Example Response
```json theme={"dark"}
{
"id": "",
"unique_name": "customer-support-agent",
"name": "Customer Support Agent",
"status": "ACTIVE",
"organization_id": "",
"deployment_type": "serverless",
"framework": "agno",
"type": "manager",
"version": 2,
"has_pending_changes": false,
"is_latest": false,
"instructions": {
"role": [
"Always greet the customer warmly",
"Search the knowledge base before answering",
"Escalate billing issues"
],
"goal": [
"Resolve customer inquiries on first contact",
"Maintain a friendly tone"
],
"general": "You are a customer support agent..."
},
"access_scope": "personal",
"model_provider": "anthropic",
"model_name": "claude-sonnet-4-5-20250929",
"tools": [],
"knowledge_bases": []
}
```
## Info
The PATCH endpoint updates agent configuration fields such as `name`, `instructions`, `model_provider`, `model_name`, `output_format`, `expected_output`, and `access_scope`. To attach tools or knowledge bases, use the [xpander.ai platform](https://chat.xpander.ai) or the [Python SDK](/api-reference/sdk).
## Notes
* At least one field must be provided in the request body
* Only the specified fields will be updated; other fields remain unchanged
* Use `deploy=true` query parameter to automatically deploy after updating
* Without `deploy=true`, changes are staged and require a separate [Deploy Agent](/api-reference/v1/agents/deploy-agent) call
* `attached_tools`, `knowledge_bases`, and `graph` can now be updated via PATCH
# Bash
Source: https://docs.xpander.ai/api-reference/v1/agents/workspace/bash
POST /v1/agents/{agent_id}/workspace/bash
Execute a shell command inside the agent's workspace
Run a shell command inside the per-agent workspace.
## Path Parameters
Agent ID (UUID)
## Request Body
Shell command to execute inside the workspace.
Maximum execution time in seconds before the command is terminated.
Optional working directory for the command. Defaults to the workspace root when empty.
## Response
Result status of the operation (e.g., `ok`).
Standard output captured from the command.
Standard error captured from the command.
Process exit code.
## Example Request
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents//workspace/bash" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"command": "ls -la",
"timeout": 300,
"working_dir": ""
}'
```
## Notes
* The workspace is per-agent and persists between calls, so files created here remain available to subsequent workspace operations for the same agent.
* Commands are run as an unprivileged user. Avoid commands that require elevated permissions.
## See Also
* [File Write](/api-reference/v1/agents/workspace/file-write)
* [File Read](/api-reference/v1/agents/workspace/file-read)
* [Grep](/api-reference/v1/agents/workspace/grep)
# File Edit
Source: https://docs.xpander.ai/api-reference/v1/agents/workspace/file-edit
POST /v1/agents/{agent_id}/workspace/file_edit
Edit a file in the agent's workspace by replacing an exact text occurrence
Edit a file in the per-agent workspace by replacing an exact text occurrence. `old_text` must match the existing file content exactly, including whitespace and indentation.
## Path Parameters
Agent ID (UUID)
## Request Body
Path to the file to edit, relative to the workspace root.
Exact text to find and replace. Must match existing file content, including whitespace.
Replacement text. Use an empty string to delete the matched content.
## Response
Result status (e.g., `ok`).
Path of the file that was edited.
## Example Request
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents//workspace/file_edit" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"path": "app.py",
"old_text": "DEBUG = True",
"new_text": "DEBUG = False"
}'
```
## Notes
* The match is exact and case-sensitive. If `old_text` appears more than once in the file, the request fails — include additional surrounding context in `old_text` to make the match unique.
* To apply several edits atomically, use [Multi Edit](/api-reference/v1/agents/workspace/multi-edit) instead.
## See Also
* [Multi Edit](/api-reference/v1/agents/workspace/multi-edit)
* [File Write](/api-reference/v1/agents/workspace/file-write)
* [File Read](/api-reference/v1/agents/workspace/file-read)
# File Read
Source: https://docs.xpander.ai/api-reference/v1/agents/workspace/file-read
POST /v1/agents/{agent_id}/workspace/file_read
Read a file from the agent's workspace filesystem
Read a file from the per-agent workspace filesystem. Optional line ranges let you page through large files without loading them entirely.
## Path Parameters
Agent ID (UUID)
## Request Body
Path to the file relative to the workspace root.
1-based line number to start reading from. Optional; reads from the beginning when omitted.
1-based line number to stop reading at (inclusive). Optional; reads to the end when omitted.
Text encoding used to decode the file contents.
## Response
Result status (e.g., `ok`).
File contents within the requested range.
The file path that was read.
## Example Request
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents//workspace/file_read" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"path": "config.yaml",
"start_line": 1,
"end_line": 50,
"encoding": "utf-8"
}'
```
## Notes
* Paths must be relative to the workspace root. Absolute paths are rejected.
* For binary files, set `encoding` appropriately or use [File Share](/api-reference/v1/agents/workspace/file-share) to retrieve the file via a public URL.
## See Also
* [File Write](/api-reference/v1/agents/workspace/file-write)
* [File Edit](/api-reference/v1/agents/workspace/file-edit)
* [Grep](/api-reference/v1/agents/workspace/grep)
# File Share
Source: https://docs.xpander.ai/api-reference/v1/agents/workspace/file-share
POST /v1/agents/{agent_id}/workspace/file_share
Publish a file from the agent's workspace to a public CDN URL
Publish a file from the per-agent workspace to a public CDN URL that can be shared externally (for example, to return a download link from an agent response).
## Path Parameters
Agent ID (UUID)
## Request Body
Path to the file in the workspace to publish.
## Response
Result status (e.g., `ok`).
Public CDN URL for the shared file.
Original workspace file path.
## Example Request
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents//workspace/file_share" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"path": "output/report.csv"
}'
```
## Notes
* Shared URLs are unauthenticated — treat them as public links. Do not share files containing secrets.
* The returned URL is served from the xpander CDN and is safe to include in agent responses or webhooks.
## See Also
* [File Write](/api-reference/v1/agents/workspace/file-write)
* [File Read](/api-reference/v1/agents/workspace/file-read)
# File Write
Source: https://docs.xpander.ai/api-reference/v1/agents/workspace/file-write
POST /v1/agents/{agent_id}/workspace/file_write
Create or overwrite a file in the agent's workspace filesystem
Create or overwrite a file in the per-agent workspace filesystem. When `create_dirs` is `true`, any missing parent directories are created automatically.
## Path Parameters
Agent ID (UUID)
## Request Body
Destination file path relative to the workspace root.
Full file content. Existing files are overwritten.
When `true`, missing parent directories are created automatically.
## Response
Result status (e.g., `ok`).
Path of the file that was written.
## Example Request
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents//workspace/file_write" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"path": "output/report.txt",
"content": "Hello World\n",
"create_dirs": true
}'
```
## Notes
* `file_write` overwrites existing files. To modify an existing file in place, prefer [File Edit](/api-reference/v1/agents/workspace/file-edit) or [Multi Edit](/api-reference/v1/agents/workspace/multi-edit).
* Paths must be relative to the workspace root.
## See Also
* [File Read](/api-reference/v1/agents/workspace/file-read)
* [File Edit](/api-reference/v1/agents/workspace/file-edit)
* [File Share](/api-reference/v1/agents/workspace/file-share)
# Glob
Source: https://docs.xpander.ai/api-reference/v1/agents/workspace/glob
POST /v1/agents/{agent_id}/workspace/glob
Find files in the agent's workspace matching a glob pattern
Find files in the per-agent workspace matching a glob pattern (e.g. `**/*.py`). Useful for discovering files before reading or editing them.
## Path Parameters
Agent ID (UUID)
## Request Body
Glob pattern to match (e.g. `**/*.py`).
Directory to search from, relative to the workspace root. Defaults to the workspace root when omitted.
Maximum number of matches to return.
## Response
Result status (e.g., `ok`).
Array of matching file paths.
## Example Request
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents//workspace/glob" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"pattern": "**/*.py",
"root_dir": "src",
"max_results": 1000
}'
```
## Notes
* Use `**` to match across directory boundaries and `*` to match anything within a single path segment.
* Combine with [Grep](/api-reference/v1/agents/workspace/grep) to search the contents of the matched files.
## See Also
* [Grep](/api-reference/v1/agents/workspace/grep)
* [File Read](/api-reference/v1/agents/workspace/file-read)
# Grep
Source: https://docs.xpander.ai/api-reference/v1/agents/workspace/grep
POST /v1/agents/{agent_id}/workspace/grep
Search for a regex pattern across files in the agent's workspace
Search for a regex pattern across files in the per-agent workspace, with optional file-type filtering and surrounding context lines.
## Path Parameters
Agent ID (UUID)
## Request Body
Regular expression to search for.
Directory or file path to search, relative to the workspace root.
Optional filename glob to include (e.g. `*.py`).
Number of context lines to include before and after each match.
## Response
Result status (e.g., `ok`).
Array of match objects, each including the file path, matching line, and surrounding context.
## Example Request
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents//workspace/grep" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"pattern": "def main",
"path": "src",
"include": "*.py",
"context_lines": 2
}'
```
## Notes
* `pattern` is a regex. Escape regex metacharacters if you want to match them literally.
* Narrow the search with `path` and `include` for faster results on large workspaces.
## See Also
* [Glob](/api-reference/v1/agents/workspace/glob)
* [File Read](/api-reference/v1/agents/workspace/file-read)
# Multi Edit
Source: https://docs.xpander.ai/api-reference/v1/agents/workspace/multi-edit
POST /v1/agents/{agent_id}/workspace/multi_edit
Apply multiple file edits atomically in the agent's workspace
Apply multiple file edits atomically. Each edit uses the same exact-match semantics as [File Edit](/api-reference/v1/agents/workspace/file-edit). If any edit fails, all changes are rolled back.
## Path Parameters
Agent ID (UUID)
## Request Body
Ordered list of edits to apply. Each item has:
Path to the file to edit, relative to the workspace root.
Exact text to replace. Must match existing file content.
Replacement text.
## Response
Result status (e.g., `ok`).
## Example Request
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/agents//workspace/multi_edit" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"edits": [
{
"path": "app.py",
"old_text": "DEBUG = True",
"new_text": "DEBUG = False"
}
]
}'
```
## Notes
* Edits are applied in the order provided. Later edits can operate on content produced by earlier edits in the same request.
* If any single edit fails (e.g., `old_text` not found), the entire batch is rolled back so the workspace is not left in a half-applied state.
## See Also
* [File Edit](/api-reference/v1/agents/workspace/file-edit)
* [File Write](/api-reference/v1/agents/workspace/file-write)
# Create Custom Function
Source: https://docs.xpander.ai/api-reference/v1/custom_functions/create-custom-function
POST /v1/custom_functions
Create a new custom function with Python source code
Create a new custom function. The code must define a function called `xpander_run_action(...)` that will be executed when the function is invoked. After creation, the function is automatically analyzed for safety and input schema extraction.
## Request Body
Display name for the custom function
Python source code. Must contain a `xpander_run_action(...)` function definition.
Internal function name (defaults to sanitized version of `name`)
Human-readable description of what the function does
Execution limits
Maximum execution time in seconds
Maximum memory in MB
## Response
Returns the created `CustomFunctionItem` with status `analysing`. The function transitions to `ready` once analysis completes.
## Example Request
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/custom_functions" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{
"name": "Weather Lookup",
"description": "Fetches current weather for a given city",
"source_code": "import requests\n\ndef xpander_run_action(city: str) -> str:\n \"\"\"Get current weather for a city.\"\"\"\n resp = requests.get(f\"https://wttr.in/{city}?format=3\")\n return resp.text"
}'
```
## Notes
* The `xpander_run_action` function is the entry point — it must be defined in the source code
* After creation, the function is automatically analyzed for safety and input schema extraction
* Status transitions: `analysing` → `ready` (success) or `analysing` → `error` (analysis failed)
* Check `analysis_error_details` if the function moves to `error` status
# Delete Custom Function
Source: https://docs.xpander.ai/api-reference/v1/custom_functions/delete-custom-function
DELETE /v1/custom_functions/{function_id}
Permanently delete a custom function
Permanently delete a custom function. Make sure to remove it from any agents' `attached_tools` and `graph` before deleting.
## Path Parameters
Unique identifier of the custom function to delete
## Response
Returns HTTP `202 Accepted` on successful deletion.
## Example Request
```bash theme={"dark"}
curl -X DELETE -H "x-api-key: " \
"https://api.xpander.ai/v1/custom_functions/"
```
## Notes
* Remove the function from any agents' `attached_tools` and `graph` before deleting
* This operation is permanent and cannot be undone
# Execute Custom Function
Source: https://docs.xpander.ai/api-reference/v1/custom_functions/execute-custom-function
POST /v1/custom_functions/{function_id}/execute
Execute a custom function with the provided parameters
Execute a custom function directly with the provided parameters. The function must be in `ready` status. Parameters are passed as key-value pairs matching the function's `input_schema`.
## Path Parameters
Unique identifier of the custom function to execute
## Request Body
Pass parameters as key-value pairs matching the function's `input_schema`. The exact fields depend on the function definition.
## Response
Returns the function execution result.
## Example Request
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/custom_functions//execute" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{"city": "San Francisco"}'
```
## Notes
* The function must be in `ready` status — functions in `analysing` or `error` status cannot be executed
* Parameters must match the function's `input_schema` (see [Get Custom Function](/api-reference/v1/custom_functions/get-custom-function))
* Useful for testing functions before attaching them to agents
# Generate Custom Function
Source: https://docs.xpander.ai/api-reference/v1/custom_functions/generate-custom-function
POST /v1/custom_functions/generate
AI-generate a custom function from a natural language description
AI-generate a custom function from a natural language description. Provide a description of what the function should do, and optionally provide existing code to improve or a cURL command to convert into a function.
## Request Body
Natural language description of what the function should do (e.g., "fetch stock prices from Yahoo Finance")
Existing Python code to improve or refactor
A cURL command to convert into a custom function
## Response
The generated Python source code ready to use with [Create Custom Function](/api-reference/v1/custom_functions/create-custom-function)
## Example Request
```bash theme={"dark"}
curl -X POST "https://api.xpander.ai/v1/custom_functions/generate" \
-H "Content-Type: application/json" \
-H "x-api-key: " \
-d '{"query": "Create a function that fetches the current Bitcoin price from CoinGecko API"}'
```
## Notes
* The generated code includes a `xpander_run_action(...)` entry point
* Review the generated code before creating the function
* You can provide `user_function` to improve existing code, or `import_curl` to convert a cURL command
# Get Custom Function
Source: https://docs.xpander.ai/api-reference/v1/custom_functions/get-custom-function
GET /v1/custom_functions/{function_id}
Get a custom function by ID, including its source code, input schema, and status
Retrieve a custom function by its ID, including the full source code, auto-extracted input schema, and current status.
## Path Parameters
Unique identifier of the custom function
## Response
Returns the full `CustomFunctionItem` object.
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/custom_functions/"
```
# List Custom Functions
Source: https://docs.xpander.ai/api-reference/v1/custom_functions/list-custom-functions
GET /v1/custom_functions
List all custom functions in the organization
List all custom functions in your organization. Custom functions are user-defined Python functions that can be attached to agents as tools.
## Query Parameters
Page number (starting from 1)
Items per page (maximum 50)
## Response
Array of custom function objects
Unique identifier for the custom function
Display name of the function
Human-readable description
Auto-generated technical description from code analysis
Function status: `analysing`, `ready`, `error`
Auto-extracted JSON schema for function parameters
Python source code of the function
Execution limits (timeout, memory, etc.)
Organization UUID
ISO timestamp of creation
Total number of custom functions
Current page number
Items per page
Total pages available
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/custom_functions?page=1&per_page=10"
```
## Notes
* Custom functions are attached to agents using `attached_tools` with `id='xpander-custom-functions'`
* Functions in `analysing` status are being processed and not yet available for use
# Update Custom Function
Source: https://docs.xpander.ai/api-reference/v1/custom_functions/update-custom-function
PATCH /v1/custom_functions/{function_id}
Update an existing custom function
Update an existing custom function. You can update the name, description, source code, and limits. If source code changes, the function is re-analyzed automatically.
## Path Parameters
Unique identifier of the custom function
## Request Body
All fields are optional. Only provided fields will be updated.
Updated display name
Updated description
Updated Python source code (triggers re-analysis)
Updated execution limits
## Response
Returns the updated `CustomFunctionItem`.
## Example Request
```bash theme={"dark"}
curl -X PATCH -H "x-api-key: " \
-H "Content-Type: application/json" \
-d '{"description": "Updated description", "source_code": "def xpander_run_action(city: str) -> str:\n return f\"Weather in {city}: Sunny\""}' \
"https://api.xpander.ai/v1/custom_functions/"
```
## Notes
* Changing `source_code` triggers automatic re-analysis — status resets to `analysing`
* Non-code fields (name, description, limits) can be updated without triggering re-analysis
# Add Documents to Knowledge Base
Source: https://docs.xpander.ai/api-reference/v1/knowledge/add-documents
POST /v1/knowledge/{kb_id}/documents
Add one or more documents to a knowledge base
Upload documents to a knowledge base by providing URLs. The documents will be downloaded, processed, and indexed for semantic search.
## Path Parameters
Unique identifier of the knowledge base (UUID format)
## Request Body
Array of document URLs to add to the knowledge base
**Supported formats:**
* PDF documents
* Microsoft Word (.docx, .doc)
* Text files (.txt, .md)
* Web pages (HTML)
* CSV and Excel files
* Presentations (PPTX, PPT)
* JSON and YAML files
## Response
Returns an array of created document objects:
Knowledge base ID
Unique identifier for the document (UUID) - initially null, assigned after processing completes
Document name (initially null)
URL of the document
## Example Request
```bash theme={"dark"}
curl -X POST -H "x-api-key: " \
-H "Content-Type: application/json" \
-d '{
"document_urls": [
"https://example.com/product-guide.pdf",
"https://example.com/faq-page"
]
}' \
https://api.xpander.ai/v1/knowledge//documents
```
## Example Response
```json theme={"dark"}
[
{
"kb_id": "",
"id": null,
"name": null,
"document_url": "https://example.com/product-guide.pdf"
},
{
"kb_id": "",
"id": null,
"name": null,
"document_url": "https://example.com/faq-page"
}
]
```
## Processing Flow
1. **Upload** - Documents are queued for processing
2. **Download** - System downloads documents from provided URLs
3. **Extract** - Text content is extracted from documents
4. **Chunk** - Content is split into searchable chunks
5. **Embed** - Chunks are converted to vector embeddings
6. **Index** - Embeddings are stored in the vector database
Processing typically takes 10-60 seconds per document depending on size.
## Supported File Types
* **Documents:** PDF, DOCX, DOC, TXT, MD, RTF
* **Spreadsheets:** CSV, XLSX, XLS
* **Presentations:** PPTX, PPT
* **Web:** HTML, XML
* **Code:** JSON, YAML, various programming languages
## Notes
* Documents must be publicly accessible via HTTP/HTTPS
* Maximum file size: 50MB per document
* The `id` field is `null` initially until the document is processed and indexed
* The document ID is assigned after processing/indexing completes
* Use [List Documents](/api-reference/v1/knowledge/list-documents) to check processing progress
* Duplicate URLs will create separate document entries
# Create Knowledge Base
Source: https://docs.xpander.ai/api-reference/v1/knowledge/create-knowledge-base
POST /v1/knowledge
Creates a new knowledge base
Create a new knowledge base in your organization to store and manage documents.
## Request Body
Display name for the knowledge base
Optional description of the knowledge base purpose
## Response
Unique identifier for the knowledge base (UUID)
Display name of the knowledge base
Description of the knowledge base (nullable)
Knowledge base type: `managed`
UUID of the organization that owns this knowledge base
Associated agent ID (nullable)
Number of documents in the knowledge base (initially 0)
## Example Request
```bash theme={"dark"}
curl -X POST -H "x-api-key: " \
-H "Content-Type: application/json" \
-d '{
"name": "Technical Documentation",
"description": "Internal technical guides and API documentation"
}' \
https://api.xpander.ai/v1/knowledge
```
## Example Response
```json theme={"dark"}
{
"id": "",
"name": "Product Catalog",
"description": "Product information and specifications for customer support",
"type": "managed",
"organization_id": "",
"agent_id": null,
"total_documents": 0
}
```
## Notes
* New knowledge bases start with zero documents
* Use the returned `id` to add documents via the [Add Documents](/api-reference/v1/knowledge/add-documents) endpoint
# Delete Knowledge Base Document
Source: https://docs.xpander.ai/api-reference/v1/knowledge/delete-document
DELETE /v1/knowledge/{kb_id}/documents/{document_id}
Delete a specific document from a knowledge base
Permanently remove a document from a knowledge base. This deletes the document file, all extracted chunks, and vector embeddings.
## Path Parameters
Unique identifier of the knowledge base (UUID format)
Unique identifier of the document to delete (UUID format)
## Response
Returns `202 Accepted` on successful deletion.
## Example Request
```bash theme={"dark"}
curl -X DELETE -H "x-api-key: " \
https://api.xpander.ai/v1/knowledge//documents/
```
## Example Response
```
HTTP/1.1 202 Accepted
Content-Type: application/json
null
```
## Notes
* This action cannot be undone
* All vector embeddings for this document will be removed from search
* Agents using this knowledge base will no longer have access to this document's content
* The document file itself is permanently deleted from storage
* Returns 404 if the document or knowledge base is not found
# Delete Knowledge Base
Source: https://docs.xpander.ai/api-reference/v1/knowledge/delete-knowledge-base
DELETE /v1/knowledge/{kb_id}
Deletes knowledge base by ID
Permanently delete a knowledge base and all its documents. This action cannot be undone.
## Path Parameters
Unique identifier of the knowledge base to delete (UUID format)
## Response
Returns `202 Accepted` on successful deletion.
## Example Request
```bash theme={"dark"}
curl -X DELETE -H "x-api-key: " \
https://api.xpander.ai/v1/knowledge/
```
## Example Response
```
HTTP/1.1 202 Accepted
Content-Type: application/json
null
```
## Notes
* All documents in the knowledge base will be permanently removed
* All vector embeddings will be deleted from the search index
* Agents using this knowledge base will lose access to it
* This action cannot be undone
* Returns 404 if the knowledge base is not found
# Get Knowledge Base Document
Source: https://docs.xpander.ai/api-reference/v1/knowledge/get-document
GET /v1/knowledge/{kb_id}/documents/{document_id}
Get detailed information about a specific document in a knowledge base
Retrieve complete details about a specific document including metadata, processing status, and content information.
## Path Parameters
Unique identifier of the knowledge base (UUID format)
Unique identifier of the document (UUID format)
## Response
Knowledge base ID this document belongs to
Unique identifier for the document (UUID)
URL of the document
UUID of the organization that owns this document
Document name (typically the document URL)
The extracted text content of the document
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/knowledge//documents/"
```
## Example Response
```json theme={"dark"}
{
"kb_id": "",
"id": "",
"document_url": "https://example.com/product-guide.pdf",
"organization_id": "",
"name": "https://example.com/product-guide.pdf",
"raw_data": "The extracted text content of the document..."
}
```
## Notes
* The `raw_data` field contains the extracted text content of the document
* Returns 404 if the document or knowledge base is not found
# Get Knowledge Base
Source: https://docs.xpander.ai/api-reference/v1/knowledge/get-knowledge-base
GET /v1/knowledge/{kb_id}
Get knowledge base details by ID
Retrieve detailed information about a specific knowledge base including its configuration, document count, and metadata.
## Path Parameters
Unique identifier of the knowledge base (UUID format)
## Response
Unique identifier for the knowledge base (UUID)
Display name of the knowledge base
Optional description of the knowledge base purpose (can be null)
Knowledge base type: `managed`
UUID of the organization that owns this knowledge base
UUID of the agent this knowledge base is attached to (can be null)
Total number of documents in the knowledge base
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
https://api.xpander.ai/v1/knowledge/
```
## Example Response
```json theme={"dark"}
{
"id": "73dc30ca-bdbf-42f7-a39f-93aff4f8522e",
"name": "Product Catalog",
"description": "Complete product information and specifications",
"type": "managed",
"organization_id": "",
"agent_id": null,
"total_documents": 12
}
```
## Notes
* Returns 404 if the knowledge base is not found or doesn't belong to your organization
* Use this endpoint to verify knowledge base existence before adding documents
# List Knowledge Base Documents
Source: https://docs.xpander.ai/api-reference/v1/knowledge/list-documents
GET /v1/knowledge/{kb_id}/documents
Get paginated list of documents in a knowledge base
Retrieve all documents stored in a specific knowledge base with pagination support. This endpoint returns document metadata including IDs and URLs.
## Path Parameters
Unique identifier of the knowledge base (UUID format)
## Query Parameters
Page number (starting from 1)
Items per page (maximum 50)
## Response
Array of document objects
Knowledge base ID this document belongs to
Unique identifier for the document (UUID)
Document name (nullable)
URL to access the document file
Total number of documents in the knowledge base
Current page number
Number of items per page
Total number of pages available
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/knowledge//documents?page=1&per_page=10"
```
## Example Response
```json theme={"dark"}
{
"items": [
{
"kb_id": "",
"id": "",
"name": "https://docs.example.com/quickstart",
"document_url": "https://docs.example.com/quickstart"
}
],
"total": 1,
"page": 1,
"per_page": 10,
"total_pages": 1
}
```
## Notes
* Documents are returned in the order they were added to the knowledge base
* The `document_url` field contains the full URL to access the document file
* Use this endpoint to audit what documents are in a knowledge base
* Combine with [Get Document](/api-reference/v1/knowledge/get-document) to retrieve full document details
# List Knowledge Bases
Source: https://docs.xpander.ai/api-reference/v1/knowledge/list-knowledge-bases
GET /v1/knowledge
Returns a paginated list of knowledge bases
Retrieve all knowledge bases in your organization with document counts and metadata.
## Query Parameters
Page number (starting from 1)
Items per page (maximum 50)
## Response
Array of knowledge base objects
Unique identifier for the knowledge base (UUID format)
Display name of the knowledge base
Description of the knowledge base content (nullable)
Knowledge base type: `managed`
Organization UUID this knowledge base belongs to
Associated agent ID (nullable)
Number of documents in this knowledge base
Total number of knowledge bases
Current page number
Number of items per page
Total number of pages available
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/knowledge?page=1&per_page=2"
```
## Example Response
```json theme={"dark"}
{
"items": [
{
"id": "73dc30ca-bdbf-42f7-a39f-93aff4f8522e",
"name": "Product Catalog",
"description": "Complete product information and specifications",
"type": "managed",
"organization_id": "",
"agent_id": null,
"total_documents": 12
},
{
"id": "e21563bd-7c02-4f8f-9520-8c854f5c2ee6",
"name": "Company Policies",
"description": "Internal policies and procedures documentation",
"type": "managed",
"organization_id": "",
"agent_id": null,
"total_documents": 8
}
],
"total": 5,
"page": 1,
"per_page": 2,
"total_pages": 3
}
```
## Notes
* Knowledge bases are automatically filtered by your organization
* `total_documents` reflects the number of documents currently indexed
* Use pagination to retrieve large lists of knowledge bases
# Search Knowledge Base
Source: https://docs.xpander.ai/api-reference/v1/knowledge/search-knowledge-base
GET /v1/knowledge/{kb_id}/search
Search in knowledge base using vector search
Perform semantic search across documents in a knowledge base using vector similarity. Returns the most relevant document chunks based on your query.
## Path Parameters
Unique identifier of the knowledge base to search (UUID format)
## Query Parameters
The search query text to find relevant documents
Number of results to return (default: 5, maximum: 50)
## Response
Returns a flat array of search results, each containing:
The extracted text content from the matching document
Relevance score (float, higher indicates better match)
## Example Request
```bash theme={"dark"}
curl --request GET \
--url 'https://api.xpander.ai/v1/knowledge//search?search_query=pricing+plans&top_k=5' \
--header 'x-api-key: '
```
## Example Response
```json theme={"dark"}
[
{
"content": "The extracted text content from the matching document...",
"score": 81.41
}
]
```
## Notes
* Search only returns results from documents with `status: "completed"`
* Pending or failed documents are excluded from search results
* Empty results indicate no matching content in the knowledge base
* Returns 404 if the knowledge base is not found
# Update Knowledge Base
Source: https://docs.xpander.ai/api-reference/v1/knowledge/update-knowledge-base
PATCH /v1/knowledge/{kb_id}
Updates a knowledge base
Modify a knowledge base's configuration. Only provided fields will be updated.
## Path Parameters
Unique identifier of the knowledge base to update (UUID format)
## Request Body
Display name for the knowledge base
Optional description of the knowledge base purpose
UUID of the agent to attach this knowledge base to
## Response
Returns the updated knowledge base object with the structure matching [Get Knowledge Base](/api-reference/v1/knowledge/get-knowledge-base).
## Example Request
```bash theme={"dark"}
curl -X PATCH -H "x-api-key: " \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Product Catalog",
"description": "Revised product information and specifications"
}' \
https://api.xpander.ai/v1/knowledge/
```
## Example Response
```json theme={"dark"}
{
"id": "",
"name": "Product Catalog v2",
"description": "Updated product information and pricing details",
"type": "managed",
"organization_id": "",
"agent_id": null,
"total_documents": 0
}
```
## Notes
* All fields in the request body are optional
* Fields not provided in the request will retain their existing values
* Returns 404 if the knowledge base is not found
# Get Database Connection
Source: https://docs.xpander.ai/api-reference/v1/misc/get-database
GET /v1/misc/db
Get PostgreSQL database connection string for your organization
Retrieve the PostgreSQL database connection details for your organization. This provides direct access to your organization's database instance for custom analytics, integrations, and data management.
## Response
Database project identifier
Database project name (typically `org_[organization_id]`)
Your organization UUID
Database connection details
Complete PostgreSQL connection string with credentials
Format: `postgresql://:@/?`
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
https://api.xpander.ai/v1/misc/db
```
## Example Response
```json theme={"dark"}
{
"id": "still-meadow-47437464",
"name": "org_f47ac10b-58cc-4372-a567-0e02b2c3d479",
"organization_id": "",
"connection_uri": {
"uri": "postgresql://:@/?sslmode=require"
}
}
```
## Usage Examples
### Python (psycopg2)
```python theme={"dark"}
import psycopg2
import requests
# Get connection string
response = requests.get(
"https://api.xpander.ai/v1/misc/db",
headers={"x-api-key": ""}
)
connection_uri = response.json()["connection_uri"]["uri"]
# Connect to database
conn = psycopg2.connect(connection_uri)
cursor = conn.cursor()
# Query data
cursor.execute("SELECT * FROM agents LIMIT 10")
results = cursor.fetchall()
cursor.close()
conn.close()
```
### Node.js (pg)
```javascript theme={"dark"}
const fetch = require('node-fetch');
const { Client } = require('pg');
// Get connection string
const response = await fetch('https://api.xpander.ai/v1/misc/db', {
headers: { 'x-api-key': '' }
});
const { connection_uri } = await response.json();
// Connect to database
const client = new Client({
connectionString: connection_uri.uri
});
await client.connect();
// Query data
const result = await client.query('SELECT * FROM agents LIMIT 10');
console.log(result.rows);
await client.end();
```
### CLI (psql)
```bash theme={"dark"}
# Get connection string and connect
psql "$(curl -s -H 'x-api-key: ' \
https://api.xpander.ai/v1/misc/db | jq -r '.connection_uri.uri')"
```
## Database Schema
Your organization database contains tables for:
* **agents** - Agent configurations and metadata
* **tasks** - Task execution records
* **knowledge\_bases** - Knowledge base metadata
* **documents** - Document records and processing status
* **users** - User information and permissions
* **organization** - Organization settings and data
* And more...
## Security Notes
* The connection string includes credentials - keep it secure
* Store the connection string as an environment variable, never in version control
* Use HTTPS only when retrieving connection strings
* The database requires SSL connections (sslmode=require)
* Be cautious with write operations to avoid accidental data modification
* Regularly rotate credentials in your organization settings
## Use Cases
* **Custom analytics** - Query task and agent data directly for reporting
* **Data export** - Extract data for external analysis and backup
* **Business intelligence** - Connect BI tools like Tableau, Metabase, Power BI
* **Integration** - Build custom integrations with third-party systems
* **Automation** - Create automated data processing pipelines
* **Advanced queries** - Perform complex SQL queries not available via REST API
## Notes
* This is a Neon PostgreSQL serverless database
* Connection pooling is handled automatically
* Database is located in AWS us-west-2 region
* SSL connections are required for security
* Connection credentials are organization-specific and should not be shared
# List LLM Models
Source: https://docs.xpander.ai/api-reference/v1/misc/list-llm-models
GET /v1/misc/llm_providers/{provider_identifier}/models
Returns available models for a specific LLM provider
List available models for a specific LLM provider. Use the `model_id` value as the agent's `model_name` field when creating or updating an agent.
## Path Parameters
The provider's `internal_identifier` from [List LLM Providers](/api-reference/v1/misc/list-llm-providers) (e.g., `openai`, `anthropic`)
## Response
Returns an array of `LLMModelItem` objects.
Model identifier — use this as the `model_name` field when creating/updating agents
Human-friendly model name
Model tier level (1 = standard, higher = premium)
Brief description of the model's capabilities
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/misc/llm_providers/openai/models"
```
## Notes
* Returns `404` if the provider identifier is not found
* Use the `model_id` value as the agent's `model_name` field
* Models are organized by tier — higher tiers indicate more capable (and more expensive) models
# List LLM Providers
Source: https://docs.xpander.ai/api-reference/v1/misc/list-llm-providers
GET /v1/misc/llm_providers
Returns a list of available LLM providers
List all available LLM providers. Use the provider's `internal_identifier` with [List LLM Models](/api-reference/v1/misc/list-llm-models) to retrieve available models.
## Response
Returns an array of `LLMProviderItem` objects.
Provider unique identifier
Provider display name (e.g., "OpenAI", "Anthropic")
Internal identifier used in API calls (e.g., `openai`, `anthropic`). Use this value as `model_provider` when creating or updating agents.
URL to the provider's logo image
Brief description of the provider
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/misc/llm_providers"
```
## Notes
* Use the `internal_identifier` value as the `model_provider` field when creating or updating agents
* To see available models for a provider, use [List LLM Models](/api-reference/v1/misc/list-llm-models) with the `internal_identifier`
# Delete Task
Source: https://docs.xpander.ai/api-reference/v1/tasks/delete-task
DELETE /v1/tasks/{task_id}
Delete a task and its associated data
Delete a task by ID. Running tasks will be cancelled before deletion, and all associated data including results and conversation history will be permanently removed.
## Path Parameters
Unique identifier of the task to delete (UUID format)
## Response
Returns `204 No Content` on successful deletion (empty response body).
## Example Request
```bash theme={"dark"}
curl -X DELETE -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks/"
```
## Response Status Codes
| Status | Meaning |
| ------ | -------------------------------------------------- |
| 204 | Task deleted successfully |
| 404 | Task not found |
| 401 | Unauthorized (invalid API key) |
| 403 | Forbidden (task belongs to different organization) |
## Important Notes
* **Permanent deletion** - This action cannot be undone
* **Running tasks** - Will be cancelled before deletion
* **Data removal** - Results, conversation history, and all associated data are removed
* **Sub-tasks** - All sub-tasks are also deleted
## Example with Error Handling
```bash theme={"dark"}
TASK_ID=""
RESPONSE=$(curl -w "\n%{http_code}" -X DELETE \
-H "x-api-key: " \
"https://api.xpander.ai/v1/tasks/$TASK_ID")
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
if [[ $HTTP_CODE == "204" ]]; then
echo "Task deleted successfully"
elif [[ $HTTP_CODE == "404" ]]; then
echo "Task not found"
else
echo "Error: $HTTP_CODE"
fi
```
## Use Cases
* **Clean up completed tasks** - Remove old task data to save storage
* **Cancel running tasks** - Stop a task that's in progress
* **Manage sensitive data** - Delete tasks containing sensitive information
* **Maintain organization** - Remove test or failed tasks
# Get Task LLM Usage
Source: https://docs.xpander.ai/api-reference/v1/tasks/get-llm-usage
GET /v1/tasks/{task_id}/llm_usage
Get LLM token usage for a specific task
Retrieve LLM token usage statistics for a specific task, including input/output token counts and the number of tool actions performed.
## Path Parameters
Unique identifier of the task (UUID format)
## Response
Unique identifier of the task
Total number of LLM tokens consumed (input + output)
Number of input (prompt) tokens consumed
Number of output (completion) tokens generated
Number of tool actions performed during the task
Whether the task used a Bring Your Own Key (BYOK) model configuration
Estimated USD cost for non-BYOK executions in this task, rounded to 5 decimal places. `0.0` means no billable usage (empty task or fully BYOK).
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks//llm_usage"
```
## Example Response
```json theme={"dark"}
{
"task_id": "e6cf93db-30c7-471b-a1a9-5051a2c9e4ba",
"tokens": 3842,
"input_tokens": 1520,
"output_tokens": 2322,
"actions": 4,
"is_byok": false,
"cost": 0.01284
}
```
## Use Cases
* **Track token consumption** - Monitor LLM token usage for individual tasks
* **Cost tracking** - `cost` is returned directly in USD, rounded to 5 decimal places (excludes BYOK executions)
* **Usage auditing** - Review resource consumption across tasks
* **BYOK tracking** - Identify which tasks ran with your own API keys vs. platform-provided keys
# Get Task
Source: https://docs.xpander.ai/api-reference/v1/tasks/get-task
GET /v1/tasks/{task_id}
Retrieve detailed information about a specific task by its unique identifier
Get complete details about a task/thread record including its current status, latest input, latest result, and execution timing. This endpoint is essential for polling async tasks and for inspecting the latest turn of a continued conversation.
## Path Parameters
Unique identifier of the task to retrieve (UUID format)
## Response
Task/thread identifier. Reuse this as `id` in later invokes to continue the same conversation.
UUID of the agent that executed this task
UUID of the organization that owns this task
Latest input stored on this task/thread record
Text message or query
Array of file references (if any)
User information (nullable)
Current task status: `pending`, `executing`, `paused`, `error`, `failed`, `completed`, or `stopped`
Latest task result. This is usually plain text or markdown. Only parse it as JSON if you explicitly requested JSON/structured output.
Output format for the latest result, such as `markdown` or `json`
ISO 8601 timestamp of when the task was created
ISO 8601 timestamp of when execution began (null if not started)
ISO 8601 timestamp of when the task finished (null if still running)
Source of the task creation: `api`, `sdk`, `dashboard`, `webhook`
Whether the task used event streaming
Array of sub-task UUIDs spawned by this task
UUID of parent task if this is a sub-task (null otherwise)
Additional metadata (nullable)
In a multi-turn conversation, this endpoint shows the latest input and latest result for the reused task/thread ID. Use [Get Task Thread](/api-reference/v1/tasks/get-thread) or [Get Task Thread (Full)](/api-reference/v1/tasks/get-thread-full) for the full message history.
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks/"
```
## Example Response
```json theme={"dark"}
{
"id": "fbd08e4d-cfa7-4838-b6e6-e51855ac2ba3",
"agent_id": "",
"organization_id": "",
"input": {
"text": "Reply with exactly SECOND",
"files": [],
"user": null
},
"status": "completed",
"created_at": "2026-03-23T00:45:26.965823Z",
"started_at": null,
"finished_at": "2026-03-23T00:45:30.532954Z",
"result": "SECOND",
"source": "api",
"output_format": "markdown",
"events_streaming": true,
"sub_executions": [],
"parent_execution": null,
"payload_extension": null
}
```
## Extracting Results
For normal text or markdown responses:
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks/" | jq -r '.result'
```
Only use `fromjson` when you explicitly requested JSON output:
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks/" | jq '.result | fromjson'
```
## Status Polling Pattern
For async workflows, poll until `status` is no longer `pending` or `executing`:
```bash theme={"dark"}
# Poll every 2 seconds until task completes
while true; do
TASK=$(curl -s -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks/")
STATUS=$(echo $TASK | jq -r '.status')
if [[ $STATUS == "completed" ]]; then
echo $TASK | jq -r '.result'
break
fi
sleep 2
done
```
## Use Cases
* **Retrieve task results** - Get final output after async execution
* **Check execution status** - Monitor if task is still executing
* **Track timing** - See `created_at`, `started_at`, `finished_at` for performance analysis
* **Get latest-turn details** - Review the most recent input and output for a continued conversation
# Get Task Thread
Source: https://docs.xpander.ai/api-reference/v1/tasks/get-thread
GET /v1/tasks/{task_id}/thread
Get task conversation thread with user and assistant messages
Retrieve the root conversation thread for a task/thread ID as a simple array. When you continue a conversation by passing the same invocation `id`, the new turns are appended here under that same task/thread ID.
## Path Parameters
Unique identifier of the task (UUID format)
## Response
Returns an array of message objects representing the root conversation:
Array of conversation messages
Unique message identifier (UUID)
Message role: `user` or `assistant`
Message content text
Unix timestamp of message creation
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks//thread"
```
## Example Response
Multi-turn conversation thread:
```json theme={"dark"}
[
{
"id": "_user_1",
"role": "user",
"content": "Reply with exactly FIRST",
"created_at": 1774226722
},
{
"id": "_agent_1",
"role": "assistant",
"content": "FIRST",
"created_at": 1774226726
},
{
"id": "_user_2",
"role": "user",
"content": "Reply with exactly SECOND",
"created_at": 1774226726
},
{
"id": "_agent_2",
"role": "assistant",
"content": "SECOND",
"created_at": 1774226730
}
]
```
## Parsing Examples
**Pretty print the conversation:**
```bash theme={"dark"}
curl -s -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks//thread" | \
jq '.[] | "\(.role): \(.content)"'
```
**Count messages in the thread:**
```bash theme={"dark"}
curl -s -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks//thread" | \
jq 'length'
```
**Extract the latest assistant response:**
```bash theme={"dark"}
curl -s -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks//thread" | \
jq '[.[] | select(.role == "assistant")][-1].content'
```
## Use Cases
* **View conversation history** - See the complete interaction between user and agent
* **Review agent responses** - Understand what the agent said and its reasoning
* **Track token usage** - Monitor LLM API costs per message
* **Audit conversations** - Review interaction history for compliance
## Notes
* Returns only the root task's messages (excludes sub-task buckets)
* Continuing a conversation with the same invocation `id` appends new turns to this array
* For multi-agent workflows with sub-tasks, use [Get Task Thread (Full)](/api-reference/v1/tasks/get-thread-full)
* Messages are ordered chronologically by creation time
# Get Task Thread (Full)
Source: https://docs.xpander.ai/api-reference/v1/tasks/get-thread-full
GET /v1/tasks/{task_id}/thread/full
Get complete conversation thread including all sub-task messages and tool calls
Retrieve the complete conversation thread for a task/thread ID, including the root conversation and any sub-task message buckets. This is the authoritative message-history endpoint for multi-turn conversations continued with the same invocation `id`.
## Path Parameters
Unique identifier of the task (UUID format)
## Response
Returns an object where `root` contains the main conversation and additional keys may appear for sub-task IDs:
Array of messages from the root task
Unique message identifier (UUID)
Message role: `user`, `assistant`, `system`, or `tool`
Message content text
Unix timestamp of message creation
For each sub-task, an array of messages with the same structure as `root`. The key is the UUID of the sub-task.
## Example Request
```bash theme={"dark"}
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks//thread/full"
```
## Example Response
```json theme={"dark"}
{
"root": [
{
"id": "_user_1",
"role": "user",
"content": "Reply with exactly FIRST",
"created_at": 1774226722
},
{
"id": "_agent_1",
"role": "assistant",
"content": "FIRST",
"created_at": 1774226726
},
{
"id": "_user_2",
"role": "user",
"content": "Reply with exactly SECOND",
"created_at": 1774226726
},
{
"id": "_agent_2",
"role": "assistant",
"content": "SECOND",
"created_at": 1774226730
}
]
}
```
## Parsing Examples
**Get all task IDs (root + sub-tasks):**
```bash theme={"dark"}
curl -s -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks//thread/full" | \
jq 'keys'
```
**Count messages in each task:**
```bash theme={"dark"}
curl -s -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks//thread/full" | \
jq 'map_values(length)'
```
**Print the root conversation:**
```bash theme={"dark"}
curl -s -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks//thread/full" | \
jq '.root[] | "\(.role): \(.content)"'
```
**Flatten all messages across root and sub-tasks:**
```bash theme={"dark"}
curl -s -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks//thread/full" | \
jq 'to_entries | map(.value[]) | .[] | "\(.role): \(.content)"'
```
## Use Cases
* **Debug multi-agent workflows** - See the complete execution tree with all sub-agents
* **Analyze token usage** - Track token consumption across all sub-tasks and calculate costs
* **Audit conversations** - Review complete interaction history including internal routing
* **Performance analysis** - Measure response times and token efficiency per sub-task
* **Troubleshoot failures** - See all tool calls and system messages that led to errors
## Comparison with /thread Endpoint
| Feature | /thread | /thread/full |
| ---------------------------- | ------- | --------------------------------------- |
| Root task messages | ✅ | ✅ |
| Multi-turn root conversation | ✅ | ✅ |
| Sub-task message buckets | ❌ | ✅ |
| Response structure | Array | Object keyed by `root` and sub-task IDs |
## Notes
* The `root` key contains the main conversation for the task/thread ID you requested
* Continuing a conversation with the same invocation `id` appends new turns to `root`
* Multi-agent or delegated runs can add extra keys for sub-task IDs
* Messages are ordered chronologically within each task bucket
## See Also
* [Get Task Thread](/api-reference/v1/tasks/get-thread) - Get the root task thread only
* [Get Task](/api-reference/v1/tasks/get-task) - Get the latest task state and result
* [List Tasks](/api-reference/v1/tasks/list-tasks) - List all tasks
# List Tasks
Source: https://docs.xpander.ai/api-reference/v1/tasks/list-tasks
GET /v1/tasks
Get paginated list of tasks with optional filtering by status, agent, or date range
Retrieve a paginated list of tasks with optional filtering by status, agent ID, or creation date. Useful for monitoring task execution across your organization or for specific agents.
## Query Parameters
Page number (starting from 1)
Items per page (maximum 50)
Filter by user ID who created the task
Filter by specific agent UUID
Filter by parent task ID (for sub-tasks)
Filter by triggering agent ID (parent calling agent in multi-agent workflows)
Filter by task status: `pending`, `executing`, `paused`, `error`, `failed`, `completed`, `stopped`
Filter by internal task processing status
Filter tasks created on or after this date (ISO 8601, e.g., `2026-02-01T00:00:00Z`)
Filter tasks created on or before this date (ISO 8601)
## Response
Array of task objects
Unique identifier for the task (UUID format)
UUID of the agent that executed this task
UUID of the user who created the task (null if created via API)
UUID of parent task if this is a subtask (null otherwise)
UUID of agent that triggered this task (null if not triggered by agent)
UUID of the organization that owns this task
Current task status: `queued`, `running`, `completed`, `failed`, `cancelled`
ISO 8601 timestamp of task creation
ISO 8601 timestamp of last update
Source that created the task (e.g., `sdk`, `api`, `webhook`)
Task execution result as JSON string (present when completed)
Task title or description (nullable)
Total number of tasks matching the filter across all pages
Current page number
Number of items returned per page
Total number of pages available
## Example Requests
```bash theme={"dark"}
# List all tasks (first page)
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks?page=1&per_page=10"
# Filter by status
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks?status=completed&page=1&per_page=10"
# Filter by agent
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks?agent_id=&page=1"
# Filter by date range
curl -X GET -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks?from_date=2026-02-01T00:00:00Z&to_date=2026-02-07T23:59:59Z"
```
## Example Response
```json theme={"dark"}
{
"items": [
{
"id": "81250b20-e9d7-4b3b-9995-07dc72b4bb59",
"agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"user_id": null,
"parent_task_id": null,
"triggering_agent_id": null,
"organization_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "completed",
"created_at": "2026-02-07T02:13:27.228497Z",
"updated_at": "2026-02-07T02:13:41.541072Z",
"source_node_type": "sdk",
"result": "{\"name\":\"xpander.ai\",\"notes\":\"Full-stack agent platform...\"}",
"title": "What is xpander.ai?"
}
],
"total": 4300,
"page": 1,
"per_page": 2,
"total_pages": 2150
}
```
## Use Cases
* **Monitor task volume** - Track total tasks and completion rates
* **Filter by agent** - See tasks for a specific agent
* **Find completed work** - Retrieve only successful task executions
* **Track recent activity** - Filter by creation date range
## See Also
* [Get Task](/api-reference/v1/tasks/get-task) - Get detailed information about a specific task
* [Stop Task](/api-reference/v1/tasks/stop-task) - Cancel a running task
* [Delete Task](/api-reference/v1/tasks/delete-task) - Permanently remove a task and its data
* [Get Task Thread](/api-reference/v1/tasks/get-thread) - Get the conversation history of a task
# Stop Task
Source: https://docs.xpander.ai/api-reference/v1/tasks/stop-task
POST /v1/tasks/{task_id}/stop
Stop a running task
Cancel a running task. Sends a stop signal to the worker executing the task, marks the execution as `stopped`, and sets `is_manually_stopped: true`. Returns the updated task record.
The endpoint is idempotent: calling it on a task that is already in a terminal state (`completed`, `failed`, `stopped`) returns the current execution unchanged.
## Path Parameters
Unique identifier of the task to stop (UUID format)
## Response
Returns the updated [Agent Execution](/api-reference/v1/tasks/get-task) object with `status` set to `stopped` and `is_manually_stopped` set to `true`.
## Example Request
```bash theme={"dark"}
curl -X POST -H "x-api-key: " \
"https://api.xpander.ai/v1/tasks//stop"
```
## Example Response
```json theme={"dark"}
{
"id": "fbd08e4d-cfa7-4838-b6e6-e51855ac2ba3",
"agent_id": "",
"organization_id": "