HTTP API
The hosted agent resources used by the TypeScript SDK are available over HTTP. Use them directly from another language, a workflow engine, or an integration that should not depend on the SDK.
Client-side SDK features are not HTTP resources. Custom tool handlers, the runtime tool catalog, local skill bundles, locally registered MCP clients, composeAgents, and automatic callback handling for human input all require SDK code in your process. Hosted MCP connections, referenced skills, files, artifacts, saved agents, durable runs, events, and manual resume are available directly over HTTP.
Base URL and authentication#
export CORESOURCE_API_KEY='your-api-key'
export CORESOURCE_API_URL='https://api.coresource.ai/v1'Every /v1 resource request carries a bearer token. /health is public.
-H "Authorization: Bearer $CORESOURCE_API_KEY"One-shot responses#
One-shot requests are synchronous and do not allocate an agent runtime or a durable run resource. They are tool-free by default; the raw endpoint can optionally enable the single hosted web_search tool with "webSearch": true.
curl --fail-with-body --silent --show-error \
-X POST "$CORESOURCE_API_URL/responses" \
-H "Authorization: Bearer $CORESOURCE_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"instructions": "Answer clearly and concisely.",
"model": "deepseek/deepseek-v4-flash",
"input": "Explain three-way invoice matching."
}' | jq -r '.output_text'The endpoint accepts input as text or a non-empty message array, plus optional instructions, model, effort, maxOutputTokens, temperature, stop, and webSearch.
Starting a run#
POST /v1/runs takes the agent definition and prompt in one request. An
agent or saga normally returns 202 Accepted with a durable run id. An
inline one-shot definition instead returns a synchronous OpenAI
Responses-shaped body: the same shape as /v1/responses, not a run resource.
RUN=$(curl --fail-with-body --silent --show-error \
-X POST "$CORESOURCE_API_URL/runs" \
-H "Authorization: Bearer $CORESOURCE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: invoice-research-1' \
--data '{
"agent": {
"type": "saga",
"systemPrompt": "Act as an evidence auditor. Prefer primary sources.",
"instructions": "Separate supported, contradicted, and unsubstantiated claims.",
"model": "openai/gpt-5.5",
"skills": ["anthropics/skills/skills/pdf"],
"outputs": ["invoice-report.md"]
},
"prompt": "Validate the invoice benchmarks and write invoice-report.md.",
"input": { "sector": "manufacturing", "region": "EU" },
"metadata": { "customerId": "customer_123" }
}')
RUN_ID=$(printf '%s' "$RUN" | jq -r '.id')| Field | Required | Notes |
|---|---|---|
agent | Yes | The agent definition, same shape as the SDK's config |
prompt | Yes | The objective |
input | No | Structured parameters for an agent or saga |
files | No | Uploaded file references for an agent or saga |
artifacts | No | Prior-run artifacts to mount for an agent or saga |
metadata | No | Correlation data stored with a durable run |
idempotencyKey | No | Also accepted as the Idempotency-Key header |
Always send an idempotency key on anything that starts durable work. If a start succeeds but its response is lost, repeating the request without the same key can create a duplicate run.
For an inline one-shot, the gateway uses prompt and the definition's inference settings. It does not pass input, files, artifacts, or run metadata into the model.
Polling and results#
# Current state.
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $CORESOURCE_API_KEY" \
"$CORESOURCE_API_URL/runs/$RUN_ID" | jq
# Final result, once terminal.
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $CORESOURCE_API_KEY" \
"$CORESOURCE_API_URL/runs/$RUN_ID/result" | jqTerminal statuses are succeeded, partial_success, failed, cancelled, and expired. queued, provisioning, running, retrying, and awaiting_input are not terminal. See core concepts.
# Projected logs.
curl -H "Authorization: Bearer $CORESOURCE_API_KEY" \
"$CORESOURCE_API_URL/runs/$RUN_ID/logs" | jq
# Stop the run.
curl -X POST -H "Authorization: Bearer $CORESOURCE_API_KEY" \
"$CORESOURCE_API_URL/runs/$RUN_ID/cancel" | jqStreaming events#
The stream is server-sent events. Depending on the run, it may carry state, progress, logs, messages, tool activity, usage, and output updates.
curl --no-buffer --fail-with-body --silent --show-error \
-H "Authorization: Bearer $CORESOURCE_API_KEY" \
-H 'Accept: text/event-stream' \
"$CORESOURCE_API_URL/runs/$RUN_ID/events"Resume with the Last-Event-ID header, or fetch retained history explicitly:
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $CORESOURCE_API_KEY" \
"$CORESOURCE_API_URL/runs/$RUN_ID/events/replay?after=EVENT_ID" | jqAs with the SDK, a dropped stream says nothing about the run. Reconnect, or poll the result.
Human input#
When an agent calls ask_user, the run enters the non-terminal awaiting_input state. Both the run and its result carry the pending action:
{
"id": "run_123",
"status": "awaiting_input",
"requiredAction": {
"type": "provide_input",
"question": "Which launch date should I use?",
"inputSchema": {
"type": "object",
"required": ["answer"],
"properties": { "answer": { "type": "string" } }
}
}
}Answer to resume the same run from its durable checkpoint:
curl --fail-with-body --silent --show-error \
-X POST "$CORESOURCE_API_URL/runs/$RUN_ID/resume" \
-H "Authorization: Bearer $CORESOURCE_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"input":{"answer":"September 15"}}' | jqThe response is normally queued or running. Keep polling the original run id. Do not create another run. The agent may pause again later.
This endpoint is what makes fully detached human-in-the-loop workflows possible: the service that answers a question does not need the handle, or the process, that started the run.
Saved agents#
Store a definition once and run it by id.
AGENT=$(curl --fail-with-body --silent --show-error \
-X POST "$CORESOURCE_API_URL/agents" \
-H "Authorization: Bearer $CORESOURCE_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"name": "invoice-researcher",
"type": "saga",
"systemPrompt": "Validate claims using primary sources.",
"model": "openai/gpt-5.5",
"outputs": ["report.md"]
}')
AGENT_ID=$(printf '%s' "$AGENT" | jq -r '.id')
curl --fail-with-body --silent --show-error \
-X POST "$CORESOURCE_API_URL/agents/$AGENT_ID/runs" \
-H "Authorization: Bearer $CORESOURCE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: nightly-2026-07-29' \
--data '{
"prompt": "Validate these invoice-management benchmarks.",
"input": { "quarter": "Q2" }
}' | jqFor one-shot saved agents this endpoint returns an OpenAI Responses-shaped body. The request remains Coresource-specific: it uses /v1/agents/{agent_id}/runs and requires prompt, so reuse an OpenAI-compatible response parser rather than assuming an OpenAI client can call the endpoint unchanged. See multi-agent orchestration.
SavedAgentRunRequest accepts prompt (required), plus agentVersion, input, files, artifacts, and metadata. The latter four fields apply to durable saved agents; the one-shot gateway transformation uses the prompt and saved inference configuration. Pin agentVersion when a run must use a stable definition. It does not make model output deterministic.
| Endpoint | Method | Purpose |
|---|---|---|
/v1/agents | POST, GET | Create, list |
/v1/agents/{agent_id} | GET, PATCH, DELETE | Retrieve, update, delete |
/v1/agents/{agent_id}/versions | GET | List immutable versions |
/v1/agents/{agent_id}/versions/{version} | GET | Retrieve one version |
/v1/agents/{agent_id}/runs | POST | Run it |
Updates use optimistic concurrency: send If-Match with the version you read, and a concurrent edit returns 409 Conflict.
Files and artifacts#
# Upload an input file.
FILE=$(curl --fail-with-body --silent --show-error \
-X POST "$CORESOURCE_API_URL/files" \
-H "Authorization: Bearer $CORESOURCE_API_KEY" \
-H 'Content-Type: text/csv' \
-H 'X-CoreSource-Filename: invoices.csv' \
--data-binary @./invoices.csv)
FILE_ID=$(printf '%s' "$FILE" | jq -r '.id')
# List a run's artifacts, then download one.
curl -H "Authorization: Bearer $CORESOURCE_API_KEY" \
"$CORESOURCE_API_URL/runs/$RUN_ID/artifacts" | jq
curl -H "Authorization: Bearer $CORESOURCE_API_KEY" \
"$CORESOURCE_API_URL/runs/$RUN_ID/artifacts/$ARTIFACT_ID/content" \
--output ./report.mdMCP connections#
Create a connection once; the credential is write-only and never returned.
curl --fail-with-body --silent --show-error \
-X POST "$CORESOURCE_API_URL/mcp/connections" \
-H "Authorization: Bearer $CORESOURCE_API_KEY" \
-H 'Content-Type: application/json' \
--data "$(jq -n --arg token "$RESEARCH_MCP_TOKEN" '{
name: "Research",
url: "https://mcp.example.com/rpc",
auth: { type: "bearer", token: $token }
}')" | jq -r '.id'For a Coresource-managed GitHub authorization send "auth":{"type":"oauth","provider":"github"} and open the returned authorization_url. To use your organization's own app, register it at /v1/mcp/oauth-apps first and reference it with "auth":{"type":"oauth","oauth_app_id":"..."}. With neither field, Coresource falls back to the standards-based path for servers supporting Client ID Metadata Documents or dynamic client registration.
Reference the connection id from an agent definition:
{
"mcpServers": [
{ "connectionId": "mcpconn_0123456789abcdef", "alias": "research", "timeoutMs": 90000 }
]
}Endpoint reference#
| Path | Methods |
|---|---|
/health | GET |
/v1/responses | POST |
/v1/runs | POST |
/v1/runs/{run_id} | GET |
/v1/runs/{run_id}/result | GET |
/v1/runs/{run_id}/cancel | POST |
/v1/runs/{run_id}/resume | POST |
/v1/runs/{run_id}/events | GET (SSE) |
/v1/runs/{run_id}/events/replay | GET |
/v1/runs/{run_id}/logs | GET |
/v1/runs/{run_id}/audit_events | GET |
/v1/runs/{run_id}/artifacts | GET |
/v1/runs/{run_id}/artifacts/{artifact_id}/content | GET |
/v1/files | POST, GET |
/v1/files/{file_id} | GET, DELETE |
/v1/files/{file_id}/content | GET |
/v1/agents | POST, GET |
/v1/agents/{agent_id} | GET, PATCH, DELETE |
/v1/agents/{agent_id}/versions | GET |
/v1/agents/{agent_id}/versions/{version} | GET |
/v1/agents/{agent_id}/runs | POST |
/v1/mcp/connections | POST, GET |
/v1/mcp/connections/{connection_id} | GET, PATCH, DELETE |
/v1/mcp/connections/{connection_id}/credentials | PUT |
/v1/mcp/connections/{connection_id}/authorize | POST |
/v1/mcp/oauth-apps | POST, GET |
/v1/mcp/oauth-apps/{oauth_app_id} | GET, PATCH, DELETE |
/v1/mcp/oauth-apps/{oauth_app_id}/credentials | PUT |
The SDK package ships the OpenAPI document for the hosted agent resource API, so you can generate a client for those declared routes:
// no-check: resolves the package's `./openapi.json` subpath export, which
// needs the published package installed rather than the source checkout
// this documentation is typechecked against.
import spec from '@coresourceai/sdk/openapi.json';The compatibility /v1/responses route, inline One shot definitions on
/v1/runs, and saved One shot agents return OpenAI Responses-shaped results.
Errors#
Failures return a JSON envelope:
{
"error": {
"code": "invalid_request",
"message": "agent.type must be one of one-shot, agent, saga"
}
}error.message is always present, and most failures carry a short error.code. Some errors add type and param fields and may leave code null. The SDK chooses an error subclass primarily from the HTTP status and preserves the server's code when one is set. See errors and retries for the mapping.
