Provider accounts and API keys
Configure model funding, manage your provider accounts, and connect with human consent.
Melso authentication and model funding are separate. Your Melso workspace API key or personal access token authorizes API calls. A provider API key, Melso Gateway credits, or your own connected subscription account pays for model execution.
For an agent-ready integration with runnable examples, read the integration skill. Use the Tasks and Runs API to submit and observe work after setup.
Authentication
The public REST base is https://melso.ai/api. Create a workspace API key
(mwk_…) in Settings → API keys, or a personal access token (mel_…) in
Profile → API tokens, and send it as a Bearer token. A workspace API key
implies its workspace; send X-Workspace-ID only with a personal access token,
because a person can belong to several workspaces:
Authorization: Bearer <workspace-api-key-or-personal-access-token>
X-Workspace-ID: <workspace-uuid-personal-access-token-only>
Content-Type: application/jsonThe harness funding routes, GET /harnesses and PUT /harnesses/{harness},
accept a signed-in browser session, a personal access token or a workspace API
key, and read or change the caller's own policy. A workspace API key has its
own policy: its Runs use Melso Gateway or a provider API key saved in that
policy, never a member's subscription account, so accounts_enabled must be
false for it. Revoking the key deletes the provider API keys saved in its
policy.
Every other endpoint on this page requires workspace membership and human
credentials: a signed-in browser session or personal access token. Provider
account mutations apply to accounts you own. Responses never expose stored
provider credentials and use Cache-Control: no-store.
Run tokens and MCP OAuth tokens cannot administer
provider accounts or harness funding. The human-only gate returns 403 for
machine actors; MCP credentials are restricted to the MCP endpoint in the
first place. Do not use MCP credentials as REST credentials. A tasks
workspace API key receives 403 workspace_key_scope on every other route on
this page. An admin key reaches the account routes other than import, for
its own identity, which never holds a subscription account: the list is
empty, routes naming an account find none, and starting a connection returns
403 with "code":"provider_account_workspace_key". Fund
a key's Runs with a provider API key in its harness policy, or Melso Gateway.
Import a local login or API key
On your own computer, run:
melso provider autolink
melso provider autolink --providers codex,claude
melso login --forward-keysAutolink lists the provider and source path or environment variable with the value redacted. Confirm each account you want to import. Interactive login also offers this review; login never uploads credentials automatically.
Supported sources are Codex ~/.codex/auth.json, Claude
~/.claude/.credentials.json, settings.json → env.ANTHROPIC_API_KEY, and
OPENAI_API_KEY / ANTHROPIC_API_KEY.
CODEX_HOME and CLAUDE_CONFIG_DIR overrides are respected. OAuth imports need
a refresh token; custom provider endpoints, credential helpers, and OS keychain
logins require connection in Settings instead.
--yes consents to the listed importable accounts. Without a terminal, explicit
consent also requires both --allow-non-interactive and --providers:
melso provider autolink --providers codex --yes --allow-non-interactiveUse a human personal access token and an HTTPS Melso server. This command is unavailable inside managed Runs. OAuth import verifies identity with the provider and may rotate the local refresh token, requiring you to log in again in the local provider CLI. If an import fails, check Settings before retrying. Expired or invalid credentials may need a fresh provider login.
Imported keys are encrypted in your vault. Existing enablement and Gateway settings are preserved; enable a new key in Settings → AI providers. Imports do not re-enable paused or revoked accounts; reconnect those in Settings.
For direct human CLI integrations, POST /api/provider-accounts/import accepts
provider (codex or claude) and exactly one of api_key or refresh_token.
Unlike browser account routes, it requires a human PAT. It returns 201 with
{status: "stored"} for a key or auth-session metadata for OAuth, never credential
material. Invalid inputs return 400, rejected credentials require reconnect
(401), and stale or disabled account imports return 409. Responses are not
cacheable. An uncertain exchange is not automatically retried.
Harnesses and models
GET /api/harnesses/{harness}/models returns 200 with {models, supported}.
Each model has id and label, and may include provider, default,
thinking.supported_levels (entries with value, label, and optional
description), thinking.default_level, and service_tiers (entries with
id, name, and optional description). Use those values for Task execution
settings instead of hardcoding model or effort lists.
The current Cloud catalog is:
| Harness | Connected account | Provider API key | Melso Gateway |
|---|---|---|---|
codex | Codex | OpenAI | Yes |
claude | Claude Code | Anthropic | Yes |
cursor | Cursor | No | No |
pi (shown as Melso) | No | No | Yes |
pi is Gateway-only. Its models come from the Melso Gateway catalog, with
Qwen3.8 27B (the default) and DeepSeek V4 Pro listed first when the catalog
includes them. For this harness, an unconfigured Gateway returns 200
with models: [] and supported: false, and a failed upstream catalog request
returns 502. The provider backend also recognizes muse, but that does not
make it an offered Cloud harness; an unknown harness returns 404. Model catalog
discovery returns 503 when unavailable and does not reserve execution capacity.
Harness access and BYOK
GET /api/provider-accounts/harnesses returns 200 with {harnesses}.
Each entry contains:
| Fields | Meaning |
|---|---|
harness, enabled | Harness identifier and overall enablement |
accounts_enabled, key_enabled, gateway_enabled | Enabled funding methods |
supports_accounts, supports_key, supports_gateway | Supported methods; Gateway also reflects deployment availability |
has_key, key_health, key_cooldown_until | Key presence and health, without the key itself |
gateway_limit_ticks, settled_ticks, reserved_ticks | Decimal integer strings for monthly cap, settled charges, and outstanding reservations |
gateway_suspended | Whether Gateway access is suspended |
next_method, next_reason | What the member's next task would use (account, api_key, or gateway), chosen by the same rules as a Run. next_method is empty when the next task cannot start, and next_reason says why (for example gateway_cap_reached or account_auth_required) |
accounts, usable_accounts | Connected accounts the member can use for the harness in this workspace, and how many can take a task now |
PUT /api/provider-accounts/harnesses/{harness} replaces the access policy.
It returns the same {harnesses} envelope (200). Send all policy fields:
omitted booleans become false. Unknown fields are rejected (400).
For an automated pipeline, use a dedicated provider project key with a provider-side spend limit. This example enables only OpenAI BYOK for Codex:
{
"enabled": true,
"accounts_enabled": false,
"key_enabled": true,
"api_key": "<dedicated-openai-project-key>",
"gateway_enabled": false,
"gateway_limit_ticks": "1000000000000"
}For Anthropic BYOK, use the claude path and an Anthropic API key. BYOK is
supported only for codex and claude. Store keys in a secret manager, never
client code, conversation input, source control, or logs.
- Omit
api_key(or send null) to preserve the stored key. - Supply a nonempty
api_keyto replace it. Keys cannot contain CR/LF and have a maximum length of 16384 bytes. - Send
api_key: ""withkey_enabled: falseto remove it. key_enabled: truerequires a stored or newly supplied key.gateway_limit_ticksis required even when Gateway is disabled. Supply a nonnegative decimal integer string of at most 30 characters, not a number.1000000000000ticks is $100. A zero value resets to the default $100 cap; it does not prohibit spending. Disable Gateway withgateway_enabled: false.- A cap below settled charges plus outstanding reservations returns 409.
Melso Gateway uses workspace credits with a per-member, per-harness monthly
cap. Enable gateway_enabled only for a supported harness, configure credits
in Melso's billing settings, and inspect the returned support and budget
fields. Saving policy does not guarantee available credits or execution.
Changing policy does not erase outstanding usage. Do not raise spending limits
without the account owner's authorization.
Model IDs that differ only in . or - between two digits name the same
Gateway model, so claude-haiku-4-5 runs as the Gateway's claude-haiku-4.5.
When Melso Gateway pays for a Run and does not serve its model for that
harness, the Run fails before it starts with failure_reason
agent_error.model_not_found_or_unavailable and is not retried. Pick another
model, or use a connected account or provider API key.
Whichever route pays for the model, BYOK included, every Cloud Run also needs
workspace access and usable workspace credits, because sandbox compute is
billed to those credits. Enterprise workspaces are exempt. Without them the
Task is still created, but its Run fails with failure_reason
free_credit_exhausted, credits_exhausted, or workspace_access_required
and is not retried automatically. Losing access or credits while a Run works
cancels it with the same reason.
Your subscription account
A subscription account belongs to one person, for their own Tasks. Follow the provider's terms. Use provider API keys for automated pipelines. Connecting an account requires that person's explicit provider consent.
All paths in this table start with /api/provider-accounts:
| Method | Suffix | Success | Behavior |
|---|---|---|---|
| GET | / | 200 {accounts} | List visible account metadata |
| GET | /{accountId} | 200 account object | Read an owned account |
| POST | /{accountId}/pause | 204 | Stop use while retaining credentials |
| POST | /{accountId}/enable | 204 | Re-enable a paused account; revoked credentials need reconnection |
| POST | /{accountId}/disable | 204 | Revoke stored credentials and cancel pending authorization |
| POST | /{accountId}/default | 204 | Select your default for this provider |
| DELETE | /defaults/{provider} | 204 | Clear the provider default |
| POST | /{accountId}/refresh-usage | 204 | Request usage refresh; read the account again for results |
| DELETE | /{accountId} | 204 | Delete the account |
These POST actions have no request body. pause and disable are deliberately
different: enabling after disable cannot restore erased credentials.
Account metadata includes id, provider, label, email, optional plan,
identity_key, tenant_key, credential_version, enabled, health,
is_owner, is_default, usage_status, usage_windows, and
usage_captured_at. Identity metadata is not an authentication credential.
Usage may be stale; a refresh request is not proof of fresh quota data.
Connect with human consent
- Call
POST /api/provider-accounts/auth-sessionswith{"provider":"codex"}(orclaude/cursor). For reconnection, also supplyreconnect_idwith the existing account UUID for that provider. - The 201 response contains
id,provider,status,prompt, andexpires_at;account_idis present after connection. Show the humanprompt.urlandprompt.user_codewhen supplied. Do not approve on their behalf. A returned URL does not prove consent. - Follow
prompt.flow:device_code(Codex) andcloud_pairing(Cursor) finish through server polling after browser consent. Forhosted_code(Claude), wait for the human's returned code and POST{"code":"<human-provided-code>"}to/api/provider-accounts/auth-sessions/{sessionId}/submit(200). - Poll
GET /api/provider-accounts/auth-sessions/{sessionId}(200), using backoff bounded byexpires_at. States includequeued,pending_user,exchanging,confirmed,connected,failed,expired, andcancelled. Treat onlyconnectedwithaccount_idas success. Other terminal states require a new human connection attempt. Sessions expire after 15 minutes. - Cancel an unfinished connection with
DELETE /api/provider-accounts/auth-sessions/{sessionId}(204).
muse is also recognized by the provider backend with a device_code flow,
but is absent from the offered Cloud catalog. Do not advertise it as available
Cloud execution.
After an uncertain submit response, read session state before doing anything
else: the authorization code may already have been consumed. A busy exchange
can return 409; respect Retry-After instead of repeatedly redeeming a code.
Errors
Error responses have error and sometimes a stable code plus details.
| Status | Meaning and action |
|---|---|
| 400 | Invalid UUID, provider, JSON, unsupported funding method, missing key, or invalid cap. Correct the request. |
| 401 | Invalid Melso authentication, or provider_account_auth_required for a provider that needs reconnection. Distinguish these before replacing credentials. |
| 403 | Human credentials or workspace access required. MCP and Run credentials cannot administer accounts. |
| 404 | Account/session unavailable to this member, or harness not offered. Check identity and scope. |
| 408 | provider_account_queue_timeout, with state: "timed_out". Inspect the Task before retrying work. |
| 409 | Busy, changed/revoked account, or a cap below committed usage. Read current state before retrying. |
| 502 | Gateway model catalog could not be fetched. Retry discovery with bounded backoff. |
| 503 | Provider accounts or the model catalog are unavailable. Retry reads with bounded backoff; surface persistent failure. |
provider_account_busy includes state: "waiting", retry_after_seconds: 2,
queue_timeout_seconds: 120, and Retry-After: 2. Other 409 responses may
not have a code. provider_account_credential_rejected tells an execution
client to update Melso; changing account credentials is not the remedy.
MCP clients
Use https://mcp.melso.ai/mcp with OAuth. MCP clients
can discover execution availability and submit work after a human configures
funding. They cannot read or manage the provider vault. See the
MCP reference for tool contracts.
Managed execution customers
An admin workspace API key can create non-login execution identities with POST /api/execution-identities: {external_id:string,name:string}. The external ID is unique within that integration and workspace; repeating it returns the original ID. GET /api/execution-identities lists its identities. DELETE /api/execution-identities/{identityId} revokes one; revoked IDs are not reused.
Send X-Execution-Identity-ID: <identity UUID> with that key to the existing provider account, OAuth auth-session, import and harness-policy endpoints. Melso verifies the identity belongs to the active key's integration and workspace. Subscription accounts, provider API keys, quotas and funding fallback belong to this customer rather than the service key. Ordinary workspace-key identities still cannot connect or borrow subscription accounts. Managed identities cannot sign in or create personal access tokens.
Create an isolated Task with execution_identity_id to bind its customer before execution begins. Future input, start, resume and question continuations retain that funding identity, including when another workspace member responds. The Task creator and retry receipt remain attributed to the API caller. The binding cannot be changed by Task updates. Revoking the identity or parent key blocks new execution and subscription credential renewal.
Managed customers use their own subscription accounts or explicit grants to that exact customer. To grant an account, send PUT /api/provider-accounts/{accountId}/execution-identities/{identityId} with the owner's X-Execution-Identity-ID; use DELETE to revoke the grant. Both customers must belong to the same integration and workspace. Workspace-wide subscription shares do not automatically grant managed customers access. Existing quota rotation and fallback apply within the accounts this customer is authorized to use.