Use an OcHub Deep Link when a provider website, account console, or setup guide should hand a ready-to-review configuration to the desktop app.
For model providers, OcHub opens an editable preview and writes nothing until
the user selects Import model provider. When the manifest contains
applyTo, the preview also shows which tools will receive the provider and
lets the user turn off any target before confirming.
Compatibility and behavior
The current protocol version is v1:
ochub://v1/import?resource=<resource>&...The model-provider resource is supported by the desktop app on macOS and by
ochcli. The desktop app handles both cold-start and already-running delivery.
Use resource=model-provider for the OcHub local gateway. Do not confuse it
with resource=provider, which imports a direct connection for one target app.
Model-provider URL
A model-provider link has one query parameter besides resource:
ochub://v1/import?resource=model-provider&payload=<base64url-json>payload is the UTF-8 JSON manifest encoded as unpadded Base64URL. It is not
ordinary Base64: use URL-safe - and _, and remove trailing = padding.
The decoded JSON may be at most 64 KiB.
Do not put apiKey in a separate query parameter. Include it in the manifest
before encoding the complete payload.
Manifest example
{
"schema": "io.ochub.model-provider/v1",
"source": {
"id": "com.aster/default",
"revision": "2026-07-01",
"website": "https://aster.example"
},
"name": "Aster API",
"apiKey": "sk-user-secret",
"dialects": ["messages", "responses"],
"models": ["claude-sonnet-4-5", "gpt-5.4"],
"websocketEnabled": true,
"endpoints": [
{
"baseUrl": "https://api.aster.example"
},
{
"baseUrl": "https://backup.aster.example"
}
],
"defaultModel": "claude-sonnet-4-5",
"modelRules": [
{
"model": "fast",
"upstreamModel": "claude-sonnet-4-5",
"dialect": "messages"
}
],
"reasoning": {
"mode": "passthrough"
},
"applyTo": [
{ "app": "codex", "preferredModel": "gpt-5.4" },
{ "app": "claude", "preferredModel": "claude-sonnet-4-5" },
{ "app": "opencode" }
],
"enabled": true,
"requires": []
}The preview masks the API key. A user may reveal or replace it before import.
The CLI requires apiKey to be present because it cannot pause for the desktop
form.
Manifest fields
| Field | Required | Meaning |
|---|---|---|
schema |
Yes | Must be io.ochub.model-provider/v1 |
name |
Yes | Display name for the model provider and generated channels |
apiKey |
For one-click import | Shared by channels generated from every endpoint |
dialects |
Yes | Provider interfaces: one or more of messages, responses, and chat |
models |
No | Models served by the provider; up to 500 unique entries; blank allows any model |
websocketEnabled |
No | Native Responses WebSocket capability shared by all endpoints; defaults to false |
endpoints |
Yes | One to eight upstream API endpoint objects |
source |
No | Stable source ID plus optional revision and website metadata |
website |
No | Provider website; overrides source.website when both exist |
defaultModel |
No | Fallback upstream model for unmatched requests |
modelRules |
No | Client-model rewrite and optional interface rules |
reasoning |
No | Reasoning handling; defaults to pass through |
applyTo |
No | Tools to configure with this provider after the user confirms the import |
enabled |
No | Initial provider/channel state; defaults to true |
requires |
No | Reserved capability list; it must currently be empty |
Each endpoint accepts:
| Field | Required | Meaning |
|---|---|---|
baseUrl |
Yes | HTTP or HTTPS base URL with a host and no embedded credentials |
Each endpoint accepts only baseUrl. Endpoints are equivalent failover
addresses and are tried in array order; they share the provider API key,
interfaces, models, and WebSocket capability. websocketEnabled: true requires
the responses dialect and means every failover address supports native
Responses WebSocket. If addresses expose different capabilities, define
separate providers.
Internally, OcHub creates one channel per endpoint and dialect. A manifest may contain at most eight endpoints and 100 model rules. A string may be at most 4 KiB. Duplicate provider dialects, models, or endpoint addresses are rejected.
Apply targets
Each applyTo entry accepts an app and an optional preferredModel.
Supported app values are claude, claude-desktop, codex, grokbuild,
opencode, openclaw, and hermes. An app may appear only once.
When provider models is not empty, preferredModel must match one of its
exact or wildcard entries. The provider must include an interface compatible
with every target, and enabled must be true when applyTo is not empty.
The desktop preview enables every requested target by default and lets the user turn targets off or change their preferred models before confirming. After confirmation, OcHub imports the provider, starts the local Gateway, and creates or switches to an OcHub-managed provider in each selected tool. The upstream API key remains in OcHub; tool configuration receives only the local Gateway address and a separate local key. If one target fails, the provider and successful targets remain installed and the failed tools are reported.
ochcli deeplink import has no confirmation screen. It imports the provider
and immediately applies every applyTo target. Successful output includes
appliedTo and applyFailures; if any target fails, the command returns a
partial-failure error with those same details.
Reasoning configuration
Omitting reasoning is equivalent to:
{
"reasoning": {
"mode": "passthrough"
}
}Supported modes are:
| Mode | Behavior |
|---|---|
passthrough |
Preserve reasoning fields from the client whenever possible |
auto |
Translate reasoning effort and token budgets between interfaces |
disabled |
Remove or disable reasoning fields before forwarding |
Automatic mapping can carry explicit budgets:
{
"reasoning": {
"mode": "auto",
"lowBudget": 4096,
"mediumBudget": 10000,
"highBudget": 16000,
"maxBudget": 32000
}
}Budgets must be positive and ordered
lowBudget ≤ mediumBudget ≤ highBudget ≤ maxBudget. Defaults are 4096, 10000,
16000, and 32000. The user can still change the mode and budgets in the import
preview.
Generate a link
Node.js:
const manifest = {
schema: "io.ochub.model-provider/v1",
name: "Aster API",
apiKey: "sk-user-secret",
dialects: ["messages", "responses"],
models: ["claude-sonnet-4-5", "gpt-5.4"],
websocketEnabled: true,
applyTo: [
{ app: "codex", preferredModel: "gpt-5.4" }
],
endpoints: [
{
baseUrl: "https://api.aster.example"
}
]
};
const payload = Buffer.from(
JSON.stringify(manifest),
"utf8"
).toString("base64url");
const url =
`ochub://v1/import?resource=model-provider&payload=${payload}`;Browser JavaScript:
function encodeBase64Url(value) {
const bytes = new TextEncoder().encode(JSON.stringify(value));
let binary = "";
for (const byte of bytes) binary += String.fromCharCode(byte);
return btoa(binary)
.replaceAll("+", "-")
.replaceAll("/", "_")
.replace(/=+$/, "");
}
const payload = encodeBase64Url(manifest);
const url =
`ochub://v1/import?resource=model-provider&payload=${payload}`;Use the resulting URL as the destination of an Import to OcHub button. A public website should generate a personal link only after authentication and should warn that the link contains the user’s API key.
Validate and test
Parse and validate without writing:
ochcli deeplink parse "$URL"Preview the mutation from automation:
ochcli --dry-run deeplink import "$URL"Apply without the desktop confirmation screen:
ochcli deeplink import "$URL"Parse and dry-run output redact secrets by default. Avoid
--show-secrets in logs, CI, and shared terminals.
The non-dry-run command also applies every applyTo target immediately.
For desktop testing on macOS:
open "$URL"Verify cold start and delivery to an already-running OcHub process. The desktop preview may be canceled without changing the database.
Other resource types
The same envelope supports existing resources:
| Resource | Required parameters | Purpose |
|---|---|---|
provider |
app, name |
Import a direct connection for one app |
mcp |
apps, config |
Import Base64-encoded MCP JSON into one or more apps |
skill |
repo |
Import a skill from a GitHub owner/name repository |
provider accepts app=claude|codex|grokbuild|opencode|openclaw|hermes, plus
optional homepage, endpoint, apiKey, model, notes, role-model fields,
configuration fields, and usage-query fields. mcp.apps is a comma-separated
list and its config uses the legacy Base64 encoding supported by that
resource. skill also accepts directory and branch.
For new local-gateway integrations, always use model-provider and its
versioned manifest instead of assembling a direct provider URL.
Security and errors
Base64URL is encoding, not encryption. Anyone who receives the link can recover the API key. Treat the full URL like the key itself:
- Do not place it in analytics, referrer logs, issue trackers, chat, or source control.
- Generate links on demand and show them only to the authenticated key owner.
- If a link leaks, rotate the API key at the provider.
- Do not log the raw URL or decoded payload.
OcHub rejects an invalid scheme, protocol version, path, schema, Base64URL,
JSON document, URL, dialect, duplicate entry, oversized payload, or unsupported
entry in requires. A rejected link does not write partial provider state.

