API reference
AgencyOSX API
Connect your AgencyOSX agents to external tools, automation workflows, and AI platforms. Use the REST API to list agents, send messages, and read your conversation history programmatically — or connect over MCP to Claude Desktop, Manus, and Cursor.
Quickstart#
Your first call in 60 seconds. Get a token at Settings → API Access, then send a message to an agent with POST /chat — the reply comes straight back as JSON.
Request
curl -X POST https://app.agencyosx.ai/api/v1/chat \
-H "Authorization: Bearer aosx_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"agentId": "kai",
"message": "Find me 10 dental clinics in Manchester"
}'Pass the returned chatId back on your next POST /chat to continue the same conversation. Each turn is billed to your wallet in USD.
Response
{
"response": "Here are 10 dental clinics in Manchester...",
"agent": { "id": "kai", "name": "Kai" },
"chatId": "d4c3b2a1-...",
"usage": { "estimated_cost_usd": 0.0854 },
"wallet": { "balanceUsd": 12.34 }
}Response
{
"response": "Here are 10 dental clinics in Manchester...",
"agent": { "id": "kai", "name": "Kai" },
"chatId": "d4c3b2a1-...",
"usage": { "estimated_cost_usd": 0.0854 },
"wallet": { "balanceUsd": 12.34 }
}Authentication#
Every endpoint requires a Bearer token. Generate an API token in your AgencyOSX dashboard under Settings → API Access, then include it in the Authorization header of every authenticated request.
Tokens are prefixed with aosx_. Keep them secret — treat them like passwords. You can revoke and regenerate tokens at any time from Settings → API Access.
HTTP header
Authorization: Bearer aosx_your_token_hereHTTP header
Authorization: Bearer aosx_your_token_hereBase URL#
All endpoint paths in this reference are relative to the base URL. Requests must be made over HTTPS.
Base URL
https://app.agencyosx.ai/api/v1Base URL
https://app.agencyosx.ai/api/v1Pagination#
Every list endpoint takes the same two query parameters and returns the same pagination object. pagination.hasMore is true while rows remain — keep increasing offset by limit until it is false.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
limitinteger · query | Optional | Rows per page (1–100). Defaults to 20; values above the cap clamp to 100. | 50 |
offsetinteger · query | Optional | Rows to skip, for pagination. Defaults to 0. | 40 |
Response fields
| Field | Meaning | Example |
|---|---|---|
total | The total number of rows that match your request across every page — the full result-set size, ignoring limit and offset. | 137 |
limit | The page size applied to this response — the most rows it can contain. Echoes your limit after defaulting to 20 and clamping to the max of 100. | 20 |
offset | How many rows were skipped before this page (zero-based). Echoes your offset; defaults to 0. With offset 40 and limit 20 this page is rows 41–60. | 40 |
hasMore | true while more rows remain beyond this page (total > offset + limit). Page forward by adding limit to offset, and stop once it is false. | true |
Paginated response
{
"clients": [ /* … up to `limit` rows … */ ],
"pagination": {
"total": 137,
"limit": 20,
"offset": 40,
"hasMore": true
}
}Paginated response
{
"clients": [ /* … up to `limit` rows … */ ],
"pagination": {
"total": 137,
"limit": 20,
"offset": 40,
"hasMore": true
}
}Sorting#
List endpoints accept sort and order. Each endpoint defines which fields it can sort by and a sensible default; the allowed fields are listed on each endpoint below. An unknown sort field or a bad order returns 400.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
sortstring · query | Optional | Field to sort by. Each endpoint lists its allowed fields; an unknown field returns 400. | created |
orderstring · query | Optional | Sort direction: "asc" or "desc". Each endpoint sets its own default. | desc |
Examples
# Sort by a field, descending
?sort=created&order=desc
# Ascending
?sort=name&order=ascExamples
# Sort by a field, descending
?sort=created&order=desc
# Ascending
?sort=name&order=ascDate ranges#
Endpoints that filter by time accept the parameters below — use either a shortcut period or an explicit startDate/endDate range, not both (a range may not exceed 366 days). On GET /account/usage a range is always applied (default 30d); on the endpoints that support it (conversations, workflow runs, receipts) it is an optional created filter.
Every date you send is interpreted in UTC, and every timestamp in a response is ISO 8601 in UTC with a trailing Z (e.g. 2026-06-28T10:00:00Z). Two input formats are accepted:
- Date only —
YYYY-MM-DD(e.g.2026-06-01), read as that day at00:00:00 UTC. A date-onlyendDatecovers the whole day, through23:59:59.999 UTC. - Full timestamp — any ISO 8601 / RFC 3339 value (e.g.
2026-06-01T09:30:00Z). To pin to a local day boundary, include an offset such as2026-06-01T00:00:00+01:00— it's converted to UTC for you.
Ranges are half-open: a row matches when created_at ≥ startDate and < endDate.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
periodstring · query | Optional | Shortcut window ending now (see the values below). Mutually exclusive with startDate/endDate. | 7d |
startDatestring · query | Optional | Inclusive lower bound. A date-only YYYY-MM-DD is read as 00:00 UTC; or pass a full ISO 8601 timestamp. Use with endDate for an explicit range. | 2026-06-01 |
endDatestring · query | Optional | Exclusive upper bound — but a date-only YYYY-MM-DD includes that whole UTC day. Full ISO 8601 timestamps allowed. Defaults to now. Range capped at 366 days. | 2026-06-30 |
period values
| Value | Meaning | Example |
|---|---|---|
today | From 00:00 UTC today until now. | ?period=today |
24h | The last 24 hours (rolling). | ?period=24h |
7d | The last 7 days. | ?period=7d |
30d | The last 30 days (default when nothing is supplied). | ?period=30d |
90d | The last 90 days. | ?period=90d |
Examples
# Shortcut period
?period=7d
# Explicit range (inclusive of both days)
?startDate=2026-06-01&endDate=2026-06-30
# Open-ended (start → now)
?startDate=2026-06-01Examples
# Shortcut period
?period=7d
# Explicit range (inclusive of both days)
?startDate=2026-06-01&endDate=2026-06-30
# Open-ended (start → now)
?startDate=2026-06-01Agents
The specialist AgencyOSX agents you can message. Browse them here, then use an agent's id with POST /chat.
/agentsAuth requiredList agents#
List every available agent — id, name, title, description, and expertise topics. The id is the agent's name lowercased (e.g. "kai"); use it anywhere an agentId is required. Paginated and sortable.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
limitinteger · query | Optional | Rows per page (1–100). Defaults to 20; values above the cap clamp to 100. | 50 |
offsetinteger · query | Optional | Rows to skip, for pagination. Defaults to 0. | 40 |
sortstring · query | Optional | Field to sort by — defaults to name. Options:
| title |
orderstring · query | Optional | Sort direction: "asc" or "desc". Defaults to asc. | desc |
Request
curl "https://app.agencyosx.ai/api/v1/agents?limit=50&sort=name&order=asc" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"agents": [
{
"id": "kai",
"name": "Kai",
"title": "Lead Generator",
"description": "I help you find and qualify ideal prospects...",
"expertiseTopics": [
"Lead list building",
"ICP definition",
"LinkedIn prospecting"
]
}
],
"pagination": { "total": 16, "limit": 20, "offset": 0, "hasMore": false }
}Request
curl "https://app.agencyosx.ai/api/v1/agents?limit=50&sort=name&order=asc" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"agents": [
{
"id": "kai",
"name": "Kai",
"title": "Lead Generator",
"description": "I help you find and qualify ideal prospects...",
"expertiseTopics": [
"Lead list building",
"ICP definition",
"LinkedIn prospecting"
]
}
],
"pagination": { "total": 16, "limit": 20, "offset": 0, "hasMore": false }
}/agents/:idAuth requiredRetrieve an agent#
Get details for a single agent. The response is a flat object (not wrapped).
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
idstring | Optional | Agent identifier — the agent's name, lowercased (e.g. "kai"). The legacy slug ("lead-generator") is also accepted. | kai |
Request
curl https://app.agencyosx.ai/api/v1/agents/kai \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"id": "kai",
"name": "Kai",
"title": "Lead Generator",
"description": "I help you find and qualify ideal prospects...",
"expertiseTopics": [
"Lead list building",
"ICP definition",
"LinkedIn prospecting"
]
}Request
curl https://app.agencyosx.ai/api/v1/agents/kai \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"id": "kai",
"name": "Kai",
"title": "Lead Generator",
"description": "I help you find and qualify ideal prospects...",
"expertiseTopics": [
"Lead list building",
"ICP definition",
"LinkedIn prospecting"
]
}Chat
Send messages to an agent and read your conversation history. Each turn is billed to your wallet and saved to a conversation you can continue.
/chatAuth requiredSend a message#
Send a message to an agent and get the agent's reply as JSON. The turn is saved to a conversation and returned as chatId — pass that chatId back to continue the same thread (the server keeps the history).
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
agentIdstring | Required | The agent to message — its public id, the agent's lowercased name (e.g. kai). Get the list from GET /agents; an unknown id returns 404. | kai |
messagestring | Required | The user's message for this turn. Up to 50,000 characters — longer messages return 400. | Find 20 marketing agencies in London |
chatIdstring | Optional | Continue an existing conversation — pass the chatId from a prior response or from GET /chat. Must belong to you and to the same agent (a mismatched agent returns 400). Omit to start a new conversation; when set, the stored history is used automatically. | d4c3b2a1-6f5e-4b8a-0d9c-2f1e4a3b5c6d |
Response fields
| Field | Meaning | Example |
|---|---|---|
response | stringThe agent's full reply for this turn, as plain text. | — |
agent | objectThe agent that answered — id (its public id) and name. | — |
chatId | stringThe conversation this turn was saved to. Pass it back as chatId on the next request to continue the same thread. | — |
usage.estimated_cost_usd | numberThe amount, in USD, charged to your wallet for this turn (OSX LLM, retail). No token counts are returned. | — |
wallet.balanceUsd | numberYour remaining wallet balance in USD after this turn was charged. | — |
Request
curl -X POST https://app.agencyosx.ai/api/v1/chat \
-H "Authorization: Bearer aosx_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"agentId": "kai",
"message": "Find me 10 dental clinics in Manchester with no social media presence"
}
// Continue that conversation on the next turn:
{
"agentId": "kai",
"chatId": "d4c3b2a1-...",
"message": "Now draft a cold email for the first three."
}'Response
{
"response": "Here are 10 dental clinics in Manchester...",
"agent": { "id": "kai", "name": "Kai" },
"chatId": "d4c3b2a1-...",
"usage": { "estimated_cost_usd": 0.0854 },
"wallet": { "balanceUsd": 12.34 }
}Request
curl -X POST https://app.agencyosx.ai/api/v1/chat \
-H "Authorization: Bearer aosx_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"agentId": "kai",
"message": "Find me 10 dental clinics in Manchester with no social media presence"
}
// Continue that conversation on the next turn:
{
"agentId": "kai",
"chatId": "d4c3b2a1-...",
"message": "Now draft a cold email for the first three."
}'Response
{
"response": "Here are 10 dental clinics in Manchester...",
"agent": { "id": "kai", "name": "Kai" },
"chatId": "d4c3b2a1-...",
"usage": { "estimated_cost_usd": 0.0854 },
"wallet": { "balanceUsd": 12.34 }
}/chatAuth requiredList conversations#
List your past conversations — both those held in the AgencyOSX app and those created via POST /chat — most recently active first. Paginated; filter by agent with agentId, and by created time with the date range.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
limitinteger · query | Optional | Rows per page (1–100). Defaults to 20; values above the cap clamp to 100. | 50 |
offsetinteger · query | Optional | Rows to skip, for pagination. Defaults to 0. | 40 |
agentIdstring · query | Optional | Only conversations with this agent. The name lowercased (e.g. "kai") or the legacy slug. | kai |
periodstring · query | Optional | Shortcut window ending now (see the values below). Mutually exclusive with startDate/endDate. | 7d |
startDatestring · query | Optional | Inclusive lower bound. A date-only YYYY-MM-DD is read as 00:00 UTC; or pass a full ISO 8601 timestamp. Use with endDate for an explicit range. | 2026-06-01 |
endDatestring · query | Optional | Exclusive upper bound — but a date-only YYYY-MM-DD includes that whole UTC day. Full ISO 8601 timestamps allowed. Defaults to now. Range capped at 366 days. | 2026-06-30 |
sortstring · query | Optional | Field to sort by — defaults to updated. Options:
| created |
orderstring · query | Optional | Sort direction: "asc" or "desc". Defaults to desc. | asc |
Response fields
| Field | Meaning | Example |
|---|---|---|
type | stringWhat the conversation is about — agent (a general conversation with an agent) or client (scoped to a specific client in your workspace). | — |
clientId | string · nullableThe client the conversation is scoped to when type is client; otherwise null. Resolve it with GET /clients. | — |
agentId | stringThe agent on the conversation — its public id (the agent's name lowercased, e.g. kai). | — |
title | stringA short title for the conversation, derived from its first message. | — |
Request
curl "https://app.agencyosx.ai/api/v1/chat?agentId=kai&limit=50&sort=created&order=desc" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"conversations": [
{
"id": "d4c3b2a1-...",
"type": "agent",
"clientId": null,
"agentId": "kai",
"title": "Manchester dental clinics",
"createdAt": "2026-06-28T10:00:00Z",
"updatedAt": "2026-06-28T10:14:00Z"
},
{
"id": "e5f6a7b8-...",
"type": "client",
"clientId": "b1f2c3d4-...",
"agentId": "mia",
"title": "Acme Dental — ad review",
"createdAt": "2026-06-27T09:00:00Z",
"updatedAt": "2026-06-27T09:20:00Z"
}
],
"pagination": { "total": 2, "limit": 20, "offset": 0, "hasMore": false }
}Request
curl "https://app.agencyosx.ai/api/v1/chat?agentId=kai&limit=50&sort=created&order=desc" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"conversations": [
{
"id": "d4c3b2a1-...",
"type": "agent",
"clientId": null,
"agentId": "kai",
"title": "Manchester dental clinics",
"createdAt": "2026-06-28T10:00:00Z",
"updatedAt": "2026-06-28T10:14:00Z"
},
{
"id": "e5f6a7b8-...",
"type": "client",
"clientId": "b1f2c3d4-...",
"agentId": "mia",
"title": "Acme Dental — ad review",
"createdAt": "2026-06-27T09:00:00Z",
"updatedAt": "2026-06-27T09:20:00Z"
}
],
"pagination": { "total": 2, "limit": 20, "offset": 0, "hasMore": false }
}/chat/:chatIdAuth requiredGet a conversation#
Retrieve one conversation and its messages, oldest first. Messages are paginated. Only conversations owned by your account are returned; anything else is a 404.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
chatIdstring | Optional | The conversation id (a UUID) from GET /chat. | d4c3b2a1-6f5e-4b8a-0d9c-2f1e4a3b5c6d |
limitinteger · query | Optional | Messages per page (1–100). Defaults to 50. | 50 |
offsetinteger · query | Optional | Messages to skip, for pagination. Defaults to 0. | 50 |
Response fields
| Field | Meaning | Example |
|---|---|---|
messages[].id | stringThe AgencyOSX message id — a UUID generated by AgencyOSX, not a model/provider message id. Stable, and unique within the conversation. | — |
messages[].role | stringWho sent the message — user (you) or agent (the AgencyOSX agent). | — |
Request
curl https://app.agencyosx.ai/api/v1/chat/d4c3b2a1-6f5e-4b8a-0d9c-2f1e4a3b5c6d \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"conversation": {
"id": "d4c3b2a1-...",
"type": "agent",
"clientId": null,
"agentId": "kai",
"title": "Manchester dental clinics",
"createdAt": "2026-06-28T10:00:00Z",
"updatedAt": "2026-06-28T10:14:00Z"
},
"messages": [
{
"id": "1a2b3c4d-...",
"role": "user",
"content": "Find me 10 dental clinics in Manchester",
"createdAt": "2026-06-28T10:00:00Z"
},
{
"id": "2b3c4d5e-...",
"role": "agent",
"content": "Here are 10 dental clinics in Manchester...",
"createdAt": "2026-06-28T10:00:09Z"
}
],
"pagination": { "total": 2, "limit": 50, "offset": 0, "hasMore": false }
}Request
curl https://app.agencyosx.ai/api/v1/chat/d4c3b2a1-6f5e-4b8a-0d9c-2f1e4a3b5c6d \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"conversation": {
"id": "d4c3b2a1-...",
"type": "agent",
"clientId": null,
"agentId": "kai",
"title": "Manchester dental clinics",
"createdAt": "2026-06-28T10:00:00Z",
"updatedAt": "2026-06-28T10:14:00Z"
},
"messages": [
{
"id": "1a2b3c4d-...",
"role": "user",
"content": "Find me 10 dental clinics in Manchester",
"createdAt": "2026-06-28T10:00:00Z"
},
{
"id": "2b3c4d5e-...",
"role": "agent",
"content": "Here are 10 dental clinics in Manchester...",
"createdAt": "2026-06-28T10:00:09Z"
}
],
"pagination": { "total": 2, "limit": 50, "offset": 0, "hasMore": false }
}Clients
The clients in your workspace. List them for context, or create one to organise an agency account's work.
/clientsAuth requiredList clients#
List the clients in your workspace, oldest first. Paginated and sortable.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
limitinteger · query | Optional | Rows per page (1–100). Defaults to 20; values above the cap clamp to 100. | 50 |
offsetinteger · query | Optional | Rows to skip, for pagination. Defaults to 0. | 40 |
sortstring · query | Optional | Field to sort by — defaults to created. Options:
| name |
orderstring · query | Optional | Sort direction: "asc" or "desc". Defaults to asc. | desc |
Request
curl "https://app.agencyosx.ai/api/v1/clients?limit=50&sort=name" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"clients": [
{
"id": "b1f2c3d4-...",
"name": "Acme Dental",
"slug": "acme-dental",
"industry": "Healthcare",
"website": "https://acmedental.com",
"brandColor": "#0ea5e9"
}
],
"pagination": { "total": 1, "limit": 20, "offset": 0, "hasMore": false }
}Request
curl "https://app.agencyosx.ai/api/v1/clients?limit=50&sort=name" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"clients": [
{
"id": "b1f2c3d4-...",
"name": "Acme Dental",
"slug": "acme-dental",
"industry": "Healthcare",
"website": "https://acmedental.com",
"brandColor": "#0ea5e9"
}
],
"pagination": { "total": 1, "limit": 20, "offset": 0, "hasMore": false }
}/clientsAuth requiredCreate a client#
Create a client in your primary workspace. Only a name is required; industry, website, and a brand colour are optional — the same fields as the app's Add client form. A URL-safe slug is generated automatically.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
namestring | Required | The client's display name (1–120 characters). | — |
industrystring | Optional | e.g. "Healthcare", "E-commerce". | — |
websitestring | Optional | The client's website. | — |
brandColorstring | Optional | The client's brand colour as a hex value (e.g. #0ea5e9). A non-hex value returns 400. | — |
Request
curl -X POST https://app.agencyosx.ai/api/v1/clients \
-H "Authorization: Bearer aosx_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Dental",
"industry": "Healthcare",
"website": "https://acmedental.com",
"brandColor": "#0ea5e9"
}'Response
// Optional fields you didn't set come back as null.
{
"client": {
"id": "b1f2c3d4-...",
"name": "Acme Dental",
"slug": "acme-dental",
"industry": "Healthcare",
"website": "https://acmedental.com",
"brandColor": "#0ea5e9"
}
}Request
curl -X POST https://app.agencyosx.ai/api/v1/clients \
-H "Authorization: Bearer aosx_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Dental",
"industry": "Healthcare",
"website": "https://acmedental.com",
"brandColor": "#0ea5e9"
}'Response
// Optional fields you didn't set come back as null.
{
"client": {
"id": "b1f2c3d4-...",
"name": "Acme Dental",
"slug": "acme-dental",
"industry": "Healthcare",
"website": "https://acmedental.com",
"brandColor": "#0ea5e9"
}
}Workflows
Multi-step agent automations. List your workflows and inspect their run history. Build and enable them in the app.
/workflowsAuth requiredList workflows#
List your workflows, most recently updated first. Paginated and sortable.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
limitinteger · query | Optional | Rows per page (1–100). Defaults to 20; values above the cap clamp to 100. | 50 |
offsetinteger · query | Optional | Rows to skip, for pagination. Defaults to 0. | 40 |
sortstring · query | Optional | Field to sort by — defaults to updated. Options:
| created |
orderstring · query | Optional | Sort direction: "asc" or "desc". Defaults to desc. | asc |
Response fields
| Field | Meaning | Example |
|---|---|---|
isActive | booleanWhether the workflow is enabled. Workflows are built, configured, and enabled in the app. | — |
Request
curl "https://app.agencyosx.ai/api/v1/workflows?limit=50&sort=updated&order=desc" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"workflows": [
{
"id": "7c3e9f10-...",
"name": "Weekly client report",
"isActive": false,
"createdAt": "2026-06-28T10:00:00Z",
"updatedAt": "2026-06-28T10:00:00Z"
}
],
"pagination": { "total": 1, "limit": 20, "offset": 0, "hasMore": false }
}Request
curl "https://app.agencyosx.ai/api/v1/workflows?limit=50&sort=updated&order=desc" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"workflows": [
{
"id": "7c3e9f10-...",
"name": "Weekly client report",
"isActive": false,
"createdAt": "2026-06-28T10:00:00Z",
"updatedAt": "2026-06-28T10:00:00Z"
}
],
"pagination": { "total": 1, "limit": 20, "offset": 0, "hasMore": false }
}/workflows/:workflowId/runsAuth requiredList workflow runs#
List the run history for one of your workflows, newest first. Each run reports its status, step progress, and the amount charged to your wallet. Paginated; startDate/endDate filter by when each run was created.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
workflowIdstring · path | Required | The workflow's id (from GET /workflows). | 7c3e9f10-2a4b-4c6d-8e0f-1a2b3c4d5e6f |
limitinteger · query | Optional | Rows per page (1–100). Defaults to 20; values above the cap clamp to 100. | 50 |
offsetinteger · query | Optional | Rows to skip, for pagination. Defaults to 0. | 40 |
periodstring · query | Optional | Shortcut window ending now (see the values below). Mutually exclusive with startDate/endDate. | 7d |
startDatestring · query | Optional | Inclusive lower bound. A date-only YYYY-MM-DD is read as 00:00 UTC; or pass a full ISO 8601 timestamp. Use with endDate for an explicit range. | 2026-06-01 |
endDatestring · query | Optional | Exclusive upper bound — but a date-only YYYY-MM-DD includes that whole UTC day. Full ISO 8601 timestamps allowed. Defaults to now. Range capped at 366 days. | 2026-06-30 |
sortstring · query | Optional | Field to sort by — defaults to created. Options:
| started |
orderstring · query | Optional | Sort direction: "asc" or "desc". Defaults to desc. | asc |
Request
curl https://app.agencyosx.ai/api/v1/workflows/7c3e9f10-2a4b-4c6d-8e0f-1a2b3c4d5e6f/runs \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"workflowId": "7c3e9f10-...",
"workflowName": "Weekly client report",
"runs": [
{
"id": "a1b2c3d4-...",
"workflowId": "7c3e9f10-...",
"status": "completed",
"triggerSource": "manual",
"inputData": { "client": "Acme Dental" },
"currentStep": 3,
"totalSteps": 3,
"chargedUsd": 0.0124,
"error": null,
"startedAt": "2026-06-28T10:05:01Z",
"completedAt": "2026-06-28T10:05:48Z",
"createdAt": "2026-06-28T10:05:00Z"
}
],
"pagination": { "total": 1, "limit": 20, "offset": 0, "hasMore": false }
}Request
curl https://app.agencyosx.ai/api/v1/workflows/7c3e9f10-2a4b-4c6d-8e0f-1a2b3c4d5e6f/runs \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"workflowId": "7c3e9f10-...",
"workflowName": "Weekly client report",
"runs": [
{
"id": "a1b2c3d4-...",
"workflowId": "7c3e9f10-...",
"status": "completed",
"triggerSource": "manual",
"inputData": { "client": "Acme Dental" },
"currentStep": 3,
"totalSteps": 3,
"chargedUsd": 0.0124,
"error": null,
"startedAt": "2026-06-28T10:05:01Z",
"completedAt": "2026-06-28T10:05:48Z",
"createdAt": "2026-06-28T10:05:00Z"
}
],
"pagination": { "total": 1, "limit": 20, "offset": 0, "hasMore": false }
}/workflows/:workflowId/runs/:runIdAuth requiredRetrieve a workflow run#
Get a single run together with the result of every step — the agent that ran, the prompt it received, its response, any files it produced, and the amount charged.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
workflowIdstring · path | Required | The workflow's id. | — |
runIdstring · path | Required | The run's id (from GET /workflows/:workflowId/runs). | — |
Response fields
| Field | Meaning | Example |
|---|---|---|
run.status | stringThe run's overall state — completed, running, failed, or queued. | — |
run.triggerSource | stringWhat started the run — manual, webhook, or schedule. | — |
run.chargedUsd | numberTotal amount, in USD, charged to your wallet for the whole run (the sum of every step's chargedUsd). | — |
run.currentStep / run.totalSteps | integerStep progress — how many of the run's steps have completed, out of the total. | — |
steps[] | arrayOne entry per step, in order. Each carries the agentId that ran, the promptSent, its response, any files produced, its own chargedUsd, and its status. | — |
Request
curl https://app.agencyosx.ai/api/v1/workflows/7c3e9f10-2a4b-4c6d-8e0f-1a2b3c4d5e6f/runs/a1b2c3d4-5e6f-4a8b-9c0d-1e2f3a4b5c6d \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"run": {
"id": "a1b2c3d4-...",
"workflowId": "7c3e9f10-...",
"status": "completed",
"triggerSource": "manual",
"inputData": { "client": "Acme Dental" },
"currentStep": 3,
"totalSteps": 3,
"chargedUsd": 0.0124,
"error": null,
"startedAt": "2026-06-28T10:05:01Z",
"completedAt": "2026-06-28T10:05:48Z",
"createdAt": "2026-06-28T10:05:00Z"
},
"steps": [
{
"id": "0f1e2d3c-...",
"stepIndex": 0,
"nodeId": "agent-1",
"agentId": "kai",
"promptSent": "Summarise this week's ad performance for Acme Dental",
"response": "This week Acme Dental's campaigns...",
"files": [],
"chargedUsd": 0.0061,
"status": "completed",
"error": null,
"startedAt": "2026-06-28T10:05:01Z",
"completedAt": "2026-06-28T10:05:22Z"
}
]
}Request
curl https://app.agencyosx.ai/api/v1/workflows/7c3e9f10-2a4b-4c6d-8e0f-1a2b3c4d5e6f/runs/a1b2c3d4-5e6f-4a8b-9c0d-1e2f3a4b5c6d \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"run": {
"id": "a1b2c3d4-...",
"workflowId": "7c3e9f10-...",
"status": "completed",
"triggerSource": "manual",
"inputData": { "client": "Acme Dental" },
"currentStep": 3,
"totalSteps": 3,
"chargedUsd": 0.0124,
"error": null,
"startedAt": "2026-06-28T10:05:01Z",
"completedAt": "2026-06-28T10:05:48Z",
"createdAt": "2026-06-28T10:05:00Z"
},
"steps": [
{
"id": "0f1e2d3c-...",
"stepIndex": 0,
"nodeId": "agent-1",
"agentId": "kai",
"promptSent": "Summarise this week's ad performance for Acme Dental",
"response": "This week Acme Dental's campaigns...",
"files": [],
"chargedUsd": 0.0061,
"status": "completed",
"error": null,
"startedAt": "2026-06-28T10:05:01Z",
"completedAt": "2026-06-28T10:05:22Z"
}
]
}Account
Your account snapshot — wallet balance and auto-top-up — plus your usage and payment receipts over a window. All money figures are in USD.
/accountAuth requiredRetrieve your account#
Get a snapshot of the token-holder's account — id, email, wallet balance, and auto-top-up status. All money figures are in dollars. For usage, call GET /account/usage; for payment receipts, GET /account/receipts.
Response fields
| Field | Meaning | Example |
|---|---|---|
wallet.balanceUsd | numberYour current Account Credits balance, in USD. Spent before pay-as-you-go. | — |
wallet.payAsYouGo | objectPay-as-you-go status — enabled (a card is on file), owedUsd (usage accrued since your credits ran out) and the creditCapUsd at which your card is charged. | — |
Request
curl https://app.agencyosx.ai/api/v1/account \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"account": {
"id": "8f7e6d5c-...",
"email": "owner@youragency.com"
},
"wallet": {
"balanceUsd": 12.34,
"payAsYouGo": { "enabled": true, "owedUsd": 0, "creditCapUsd": 25 }
}
}Request
curl https://app.agencyosx.ai/api/v1/account \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"account": {
"id": "8f7e6d5c-...",
"email": "owner@youragency.com"
},
"wallet": {
"balanceUsd": 12.34,
"payAsYouGo": { "enabled": true, "owedUsd": 0, "creditCapUsd": 25 }
}
}/account/usageAuth requiredGet usage#
Your retail spend over a window — the total charged to your wallet, broken down by agent and per day.
Notes
- Pick the window with a
periodshortcut (todayfor current usage;7d/30d/90d) or an explicitstartDate/endDaterange. - Defaults to the last 30 days when nothing is supplied.
- All cost figures are the amount charged to your wallet, in USD (retail) — never token counts.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
periodstring · query | Optional | Shortcut window ending now (see the values below). Mutually exclusive with startDate/endDate. | 7d |
startDatestring · query | Optional | Inclusive lower bound. A date-only YYYY-MM-DD is read as 00:00 UTC; or pass a full ISO 8601 timestamp. Use with endDate for an explicit range. | 2026-06-01 |
endDatestring · query | Optional | Exclusive upper bound — but a date-only YYYY-MM-DD includes that whole UTC day. Full ISO 8601 timestamps allowed. Defaults to now. Range capped at 366 days. | 2026-06-30 |
Response fields
| Field | Meaning | Example |
|---|---|---|
period | stringEchoes the window you requested — one of today, 24h, 7d, 30d, 90d, or custom for an explicit startDate/endDate range. | — |
totalCostUsd | numberThe total amount charged to your wallet over the window, in USD (retail). Equals the sum of every agent's costUsd. | — |
byAgent | objectRetail spend keyed by agent — each agent's public id (e.g. kai) mapped to its costUsd for the window. Spend that can't be attributed to an agent appears under unknown. | — |
dailyBreakdown | arrayOne row per UTC day with spend in the window — newest first — each with date and costUsd. | — |
Request
curl "https://app.agencyosx.ai/api/v1/account/usage?period=30d" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"period": "30d",
"startDate": "2026-05-30T00:00:00.000Z",
"endDate": "2026-06-29T12:00:00.000Z",
"currency": "usd",
"totalCostUsd": 4.82,
"byAgent": {
"kai": { "costUsd": 3.10 },
"finn": { "costUsd": 1.72 }
},
"dailyBreakdown": [
{ "date": "2026-06-29", "costUsd": 0.21 },
{ "date": "2026-06-28", "costUsd": 0.64 }
]
}Request
curl "https://app.agencyosx.ai/api/v1/account/usage?period=30d" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"period": "30d",
"startDate": "2026-05-30T00:00:00.000Z",
"endDate": "2026-06-29T12:00:00.000Z",
"currency": "usd",
"totalCostUsd": 4.82,
"byAgent": {
"kai": { "costUsd": 3.10 },
"finn": { "costUsd": 1.72 }
},
"dailyBreakdown": [
{ "date": "2026-06-29", "costUsd": 0.21 },
{ "date": "2026-06-28", "costUsd": 0.64 }
]
}/account/receiptsAuth requiredList receipts#
List your wallet payments and refunds — every top-up (manual and automatic) plus any refund — newest first. Paginated; filter by date with the standard range. Usage charges aren't receipts; for those, see GET /account/usage.
Parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
limitinteger · query | Optional | Rows per page (1–100). Defaults to 20; values above the cap clamp to 100. | 50 |
offsetinteger · query | Optional | Rows to skip, for pagination. Defaults to 0. | 40 |
periodstring · query | Optional | Shortcut window ending now (see the values below). Mutually exclusive with startDate/endDate. | 7d |
startDatestring · query | Optional | Inclusive lower bound. A date-only YYYY-MM-DD is read as 00:00 UTC; or pass a full ISO 8601 timestamp. Use with endDate for an explicit range. | 2026-06-01 |
endDatestring · query | Optional | Exclusive upper bound — but a date-only YYYY-MM-DD includes that whole UTC day. Full ISO 8601 timestamps allowed. Defaults to now. Range capped at 366 days. | 2026-06-30 |
Response fields
| Field | Meaning | Example |
|---|---|---|
type | stringWhat the entry is — topup (you topped up), auto_topup (a saved card was charged automatically), refund, or reversal. | — |
amountUsd | numberThe payment amount in USD, always positive — type indicates whether it was money in or a refund. | — |
receiptUrl | string · nullableA link to the Stripe receipt for the payment, or null when none is available (e.g. for some refunds). | — |
Request
curl "https://app.agencyosx.ai/api/v1/account/receipts?period=90d" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"receipts": [
{
"id": "c4d5e6f7-...",
"date": "2026-06-28T09:30:00Z",
"type": "topup",
"amountUsd": 25,
"status": "succeeded",
"receiptUrl": "https://pay.stripe.com/receipts/..."
}
],
"pagination": { "total": 1, "limit": 20, "offset": 0, "hasMore": false }
}Request
curl "https://app.agencyosx.ai/api/v1/account/receipts?period=90d" \
-H "Authorization: Bearer aosx_your_token_here"Response
{
"receipts": [
{
"id": "c4d5e6f7-...",
"date": "2026-06-28T09:30:00Z",
"type": "topup",
"amountUsd": 25,
"status": "succeeded",
"receiptUrl": "https://pay.stripe.com/receipts/..."
}
],
"pagination": { "total": 1, "limit": 20, "offset": 0, "hasMore": false }
}MCP integration#
AgencyOSX exposes a remote Model Context Protocol (MCP) server, so you can connect your agents directly to Claude Code, Claude Desktop, Manus, Cursor, or any MCP-compatible client. No local server required — your client connects to the hosted endpoint.
Every method — initialize, tools/list, and tools/call — requires your Bearer token. MCP clients send it on every request, so set it once in your client config. Protocol errors are returned as JSON-RPC error objects.
Claude Code (CLI)
The fastest path. Grab a token from Settings → API Access, then run one command:
# Add AgencyOSX to Claude Code (one command)
claude mcp add --transport http agencyosx https://app.agencyosx.ai/api/mcp \
--header "Authorization: Bearer aosx_your_token_here"
# Verify it connected (should show "agencyosx" with 2 tools)
claude mcp list
# Share it with your team via a committed .mcp.json instead:
claude mcp add --transport http agencyosx --scope project \
https://app.agencyosx.ai/api/mcp \
--header "Authorization: Bearer aosx_your_token_here"Confirm with claude mcp list or /mcp inside Claude Code — you'll see agencyosx with its tools. MCP tool calls must return within ~60s, so keep individual requests focused.
Claude Desktop
Add the following to your claude_desktop_config.json:
{
"mcpServers": {
"agencyosx": {
"url": "https://app.agencyosx.ai/api/mcp",
"headers": {
"Authorization": "Bearer aosx_your_token_here"
}
}
}
}Manus
Manus supports remote MCP servers natively. Point it at the same endpoint:
Server URL: https://app.agencyosx.ai/api/mcp
Authorization: Bearer aosx_your_token_hereAvailable MCP tools
list_agentsList all available AgencyOSX agents with their expertise areas.
ask_agentChat with an AgencyOSX specialist agent and get the response back as text.
Code examples#
A complete script — list agents, chat, and read your conversation history — in your language of choice.
# List all agents
curl https://app.agencyosx.ai/api/v1/agents \
-H "Authorization: Bearer aosx_your_token_here"
# Chat with an agent
curl -X POST https://app.agencyosx.ai/api/v1/chat \
-H "Authorization: Bearer aosx_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"agentId": "kai",
"message": "Find me 10 dental clinics in Manchester"
}'
# List your past conversations with an agent
curl "https://app.agencyosx.ai/api/v1/chat?agentId=kai" \
-H "Authorization: Bearer aosx_your_token_here"
# Read one conversation's full history
curl https://app.agencyosx.ai/api/v1/chat/d4c3b2a1-6f5e-4b8a-0d9c-2f1e4a3b5c6d \
-H "Authorization: Bearer aosx_your_token_here"Rate limits#
Rate limits are applied per account — shared across all of your API tokens, so adding tokens does not raise your limit. When a limit is exceeded, the API returns 429 Too Many Requests. Wait the stated window before retrying.
| Endpoint | Limit | Window |
|---|---|---|
POST /chat | 60 requests | Per minute |
GET /chat, GET /chat/:chatId | 120 requests | Per minute |
POST /api/mcp (tools/call) | 60 requests | Per minute |
GET /agents, GET /agents/:id | 120 requests | Per minute |
GET /clients, GET /workflows | 120 requests | Per minute |
POST /clients | 30 requests | Per minute |
GET /workflows/:id/runs (+ /:runId) | 120 requests | Per minute |
GET /account, GET /account/usage, GET /account/receipts | 120 requests | Per minute |
Billable endpoints (e.g. POST /chat) run on OSX LLM and are charged to your AgencyOSX wallet in USD. Check your balance and spend with GET /account and GET /account/usage.
Example 429
{
"error": "Rate limit exceeded. Maximum 60 requests per minute."
}Example 429
{
"error": "Rate limit exceeded. Maximum 60 requests per minute."
}Error handling#
Error responses are a flat JSON object with an error field. The HTTP status code carries the semantic meaning.
| Status | Meaning |
|---|---|
400 | Bad request — missing/invalid parameters, or an input over the size limit |
401 | Unauthorized — missing, invalid, revoked, or expired API token |
402 | Payment required — wallet balance too low; add funds or enable auto top-up in Settings → Billing |
403 | Forbidden — the account is suspended; API access is disabled |
404 | Not found — the agent or conversation does not exist (or isn't yours) |
429 | Rate limited — the per-minute request limit or the daily safety cap was reached; wait and retry |
500 | Internal error — contact support if persistent |
502 | Upstream error — the underlying model provider failed; retry shortly |
503 | Service unavailable — the model service is temporarily unavailable; retry shortly |
Error response
{
"error": "The provided API token is invalid or has been revoked."
}Error response
{
"error": "The provided API token is invalid or has been revoked."
}