Skip to main content
A connection is a third-party account your Crevio account has linked — a Gmail inbox, a Notion workspace, a Slack team, an ad account. The Connections API is one surface over all of them: the same endpoints list, inspect, run, rename, and disconnect every family, and the transport underneath never appears in the contract. Under the hood a connection is one of several things — an OAuth app connection, a remote MCP server, a social or ads channel — but you address all of them the same way, by a single unified id.

The unified id

Every connection carries one id, returned by GET /connections and GET /connections/connected. Treat it as opaque — store it and pass it back verbatim wherever an endpoint takes {id}. Don’t parse it or build one yourself; its internal shape is not part of the contract. Alongside it, kind tells you which family the connection belongs to — an app connection, a remote MCP server, a social or ads channel, or a native integration. Compare that value if you need to branch, but you rarely do: listing, inspecting, and disconnecting work identically across families. Only execute and proxy care, and they tell you when you’ve reached for the wrong one.

Connecting an app

POST /connections/connect mints a hosted OAuth link — no frontend SDK required. Send the user to redirect_url; when they come back, the connection shows up in GET /connections/connected.
proxy and the rename endpoint are new; the TypeScript SDK picks them up on its next generated release. Call them over REST in the meantime — every other connection operation is already available as crevio.connections.*.
Pass scope: "user" to make the connection personal to the calling user rather than shared with the whole account. Personal connections are invisible to everyone else on the account — use them when each teammate links their own inbox, and the default (team) when the business links its one Notion.

What’s connected

status: "error" does not mean the connection is gone. The record survives — along with its approval policies and its place in your UI — so the user can reconnect the same app rather than setting it up from scratch. Calls through it fail until they do. Surface it as “needs reconnecting”, not “disconnected”.

Running a tool

Most apps expose a fixed set of actions. GET /connections/{id}/tools lists them with the approval policy each one resolves to for this account:
policy is what will actually happen; default_policy is what Crevio classified the tool as before any account override. Both are one of: Reads generally classify as always_allow and writes as always_ask. Account owners override any tool from the dashboard’s approval settings.
arguments is passed through to the provider verbatim — Crevio does not reshape it. Get the exact field names from the tool’s own schema rather than guessing.

When a call needs approval

A 202 is not an error. It means the action was frozen intact, and the response body is the Approval that’s now waiting:
Resolve it with POST /approvals/{id}/approve or /deny. Approving replays the exact frozen request — you don’t re-send it yourself, and re-sending it creates a second approval rather than executing the first.

Calling an app’s API directly

Tools cover the common actions. When the thing you need isn’t among them — an unusual endpoint, a field mask, a filter the action can’t express — POST /connections/{id}/proxy makes an authenticated HTTP request to the app’s own API on the connection’s behalf.
Never send a credential. The connected account’s token is injected server-side and is never held by Crevio nor exposed to the caller. Authorization, Host, Cookie, Accept-Encoding, Content-Length, and Connection are stripped from headers — an Authorization you set yourself would fight the injected credential rather than authenticating anything.

Reading the response

status is the app’s status code, not Crevio’s. A 200 from this endpoint with "status": 404 in the body means the call succeeded and the app answered “not found” — that’s an answer to read, not a failure to retry. Crevio’s own HTTP status only reports whether the request could be made at all. truncated: true means the app’s response exceeded 256 KB and body was cut. Paginate or narrow the query rather than working from a partial payload.

Governance

The proxy is gated exactly like a tool call, keyed on the method: reads run now, writes freeze a 202 approval, and an account override still wins. That’s what stops the raw-request path from being a way around the approval a named tool would have asked for.
Prefer a real tool when one exists. It validates its inputs and reads far better in the approval card a human has to decide on. Reach for the proxy when nothing covers the endpoint.

What can’t be proxied

Naming a connection

With two Gmails linked, “work gmail” and “support gmail” is what makes a connection addressable by a human — and what an agent echoes back when it asks which account to act on.
The nickname is up to 60 characters and becomes the connection’s label. Send an empty string to clear it and fall back to the provider’s own label. Only app connections can be renamed — every other family takes its name from a record the provider owns, and a rename there would be overwritten on the next sync (422 not_renameable).

Disconnecting

Revokes upstream where the provider supports it and prunes the local record either way.

Errors

Beyond the standard error codes, these are specific to connections:

Approvals

Resolve the pending actions that gated writes freeze.

Agents overview

How connections become capabilities an agent can use on a schedule.