Reference
Base URL
https://coreloop.run/anthropic. The SDK appends /v1 itself. Every path below is relative to the base URL.
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://coreloop.run/anthropic",
apiKey: process.env.CORELOOP_API_KEY,
});Headers
| Header | Notes |
|---|---|
| x-api-key | Required. A coreloop key. The key selects the organization. |
| anthropic-version | Accepted. Never required. |
| anthropic-beta | Accepted. Never required. |
| request-id | On every response. Quote it when reporting a problem. |
Errors
{
"type": "error",
"error": {
"type": "not_found_error",
"message": "session not found: sesn_..."
},
"request_id": "req_..."
}| Type | Status | Cause |
|---|---|---|
| invalid_request_error | 400 | The request is malformed, or the resource is archived. |
| authentication_error | 401 | No key, or a key that is revoked or expired. |
| permission_error | 403 | The organization is waitlisted. |
| not_found_error | 404 | No such resource, or no such route. |
| api_error | 500 | Ours. |
coreloop refuses a request over 32 MiB, and a skills upload over 30 MB, with request_too_large and 413, before the request gets an id.
A send takes at most 50 events, and a session create at most 50 initial_events. More is 400.
Pagination
limitdefaults to 20. Its ceiling is 100 on the agent, session, vault and credential lists and 1000 elsewhere. A value outside the range is 400.pagetakes thenext_pagecursor of the previous page.- On the last page the environment and skill lists carry
next_page: null. The rest omit the field. - A query parameter an endpoint does not define is 400.
Event types
What a session writes to its transcript. Webhooks carry their own types, listed on the webhooks page.
| Type | Fields |
|---|---|
| user.message | content |
| user.interrupt | none |
| user.tool_confirmation | tool_use_id, result, deny_message |
| agent.message | content |
| agent.thinking | none |
| agent.tool_use | name, input, evaluated_permission, evaluation |
| agent.tool_result | tool_use_id, content, is_error |
| agent.mcp_tool_use | name, mcp_server_name, input, evaluated_permission, evaluation |
| agent.mcp_tool_result | mcp_tool_use_id, content, is_error |
| agent.custom_tool_use | name, input |
| agent.thread_context_compacted | none |
| user.custom_tool_result | custom_tool_use_id, content, is_error |
| session.status_running | none |
| session.status_idle | stop_reason: end_turn, requires_action with event_ids, retries_exhausted, or budget_reached |
| session.error | error, with a retry_status; an MCP error also names mcp_server_name |
| session.updated | the fields that changed: agent, title, metadata, budget |
| session.usage | usage, the session's totals, and budget while one is set; sent before each idle but a retries_exhausted one |
| span.model_request_start | none |
| span.model_request_end | model_request_start_id, is_error, model_usage |
Id prefixes
| Prefix | Resource |
|---|---|
| agent_ | An agent |
| env_ | An environment |
| sesn_ | A session |
| sevt_ | A session event |
| skill_ | A skill |
| skver_ | A skill version |
| vlt_ | A vault |
| vcrd_ | A vault credential |
| req_ | A request |
| whe_ | A webhook event |
Models and providers
Any model your keys serve. coreloop picks the first provider on the organization that can serve the id, and rewrites the id for that provider.
| Model | Served by |
|---|---|
| claude-sonnet-5 | Anthropic, or OpenRouter when there is no Anthropic key. |
| gpt-5.6 | OpenAI, or OpenRouter when there is no OpenAI key. |
| openrouter/moonshotai/kimi-k3 | OpenRouter, always. |
| anthropic/claude-opus-5 | Anthropic, or OpenRouter. |
| openai/gpt-5.6 | OpenAI, or OpenRouter. |
| z-ai/glm-5.2 | OpenRouter. |
Endpoints
- POST/v1/agents
- GET/v1/agents
- GET/v1/agents/:id
- POST/v1/agents/:id
- GET/v1/agents/:id/versions
- POST/v1/agents/:id/archive
- POST/v1/environments
- GET/v1/environments
- GET/v1/environments/:id
- POST/v1/environments/:id
- POST/v1/environments/:id/archive
- POST/v1/sessions
- GET/v1/sessions
- GET/v1/sessions/:id
- POST/v1/sessions/:id
- POST/v1/sessions/:id/archive
- DELETE/v1/sessions/:id
- POST/v1/sessions/:id/events
- GET/v1/sessions/:id/events
- GET/v1/sessions/:id/events/stream
- POST/v1/skills
- GET/v1/skills
- GET/v1/skills/:id
- DELETE/v1/skills/:id
- POST/v1/skills/:id/versions
- GET/v1/skills/:id/versions
- GET/v1/skills/:id/versions/:version
- GET/v1/skills/:id/versions/:version/content
- DELETE/v1/skills/:id/versions/:version
- POST/v1/vaults
- GET/v1/vaults
- GET/v1/vaults/:id
- POST/v1/vaults/:id
- POST/v1/vaults/:id/archive
- DELETE/v1/vaults/:id
- POST/v1/vaults/:id/credentials
- GET/v1/vaults/:id/credentials
- GET/v1/vaults/:id/credentials/:credential_id
- POST/v1/vaults/:id/credentials/:credential_id
- POST/v1/vaults/:id/credentials/:credential_id/archive
- POST/v1/vaults/:id/credentials/:credential_id/mcp_oauth_validate
- DELETE/v1/vaults/:id/credentials/:credential_id
Vaults
A vault holds credentials for MCP servers, one per server URL. A credential takes a static_bearer token or an mcp_oauth grant; environment_variable is 400. Every secret is encrypted at rest and no response returns it. Archiving a credential or its vault deletes its secrets.
An mcp_oauth grant with a refresh block is refreshed when a minute or less is left, and when its server refuses the token. A refresh the token endpoint refuses, with a 4xx or a 2xx that is not JSON, invalidates the credential and sends vault_credential.refresh_failed; an update with a new access or refresh token clears it. An expired token is still presented, and the server decides; one the server refuses with no way to refresh it is invalidated. mcp_oauth_validate probes the server and answers valid, invalid or unknown.
Five differences from the Managed Agents API. A refresh never follows a redirect, and keeps the grant, where the Managed Agents API follows it. Under client_secret_basic it sends client_id only in the Basic header. The bodies mcp_oauth_validate echoes are scrubbed of every secret the credential holds, and are cut at 4096 characters without redacting long runs. A token whose lifetime is within the minute is refreshed once per connection, where the Managed Agents API refreshes it before every request.
A turn presents a credential to the MCP server whose URL it holds, from the vaults its session names in vault_ids.
An end user's own models
Not in the Managed Agents API. A vault can also hold an end user's own model credentials, so their sessions run on their keys or their ChatGPT subscription instead of the organization's. auth.type model_api_key takes a provider (openai, anthropic or openrouter) and an api_key. The key is read against its provider before it is stored: one the provider calls invalid answers 400 invalid_request_error with the provider's words, and an outage or a slow provider stores it unchecked. openai_subscription takes nothing else: the create answers auth.connection with a user_code and a verification_uri to show the end user, and its status is pending. A retrieve while pending asks OpenAI, at most once every 5 seconds, and answers connected once the end user approved, or failed with a message. An update with the same auth starts a new code on the same credential; its old tokens serve until the new ones land. A new code the end user refuses leaves it connected on the old tokens, with the refusal as its message.
A vault holds one model credential per provider, and openai_subscription is a provider of its own. A second answers 409 until the first is archived.
A session's coreloop.payer, set at create and fixed after, says who pays: organization, the default, or end_user. An organization's session runs on the organization's keys and ignores the model credentials in its vaults. An end user's session runs only on the model credentials in its vaults, never on the organization's keys. Each call takes the model's first provider with a credential that serves it, across the session's vaults in vault_ids order. A GPT model tries the subscription, then openai, then openrouter; a Claude model tries anthropic, then openrouter. A subscription that is broken, spent until its reset, or does not list the model is skipped. With none left, the turn stops with an error naming why, and the session waits for the client's next message.
Not built yet
These are part of the Managed Agents API and coreloop does not run them. coreloop stores any configuration for them that a request carries and echoes it back.
- web_fetch's
url_sources: refused, not stored. - Outcomes, and the
system.messageevent. - Multi-agent session threads.
- Files and memory stores.
- Scheduled deployments.
- Self-hosted sandboxes, and network policies on an environment.
- Anthropic's pre-built skills.