Skip to main content
Every request carries its credential the same way, whichever kind it is:
This differs from the direct REST API, where an API key normally uses the token prefix and only an OAuth token uses Bearer. Over MCP, always use Bearer — the server inspects the credential and routes it to the verification path that recognizes it.

API key

For headless and CI use, or clients that cannot run a browser flow. An API key from Settings → Integrations → API is user-scoped, carries the THIRD_PARTY_OPERATION scope, and is the same credential the Lofty CLI reads from LOFTY_CUSTOMER_KEY. Send it as Authorization: Bearer <key> using any of the client configurations.

OAuth 2.0 authorization code + PKCE

The recommended path. A client discovers the flow on its own: an unauthenticated call returns 401 with a WWW-Authenticate header naming the resource metadata, and the client follows that to the authorization server. Nothing is configured by hand.
PKCE with S256 is mandatory and enforced at both ends. Public clients authenticate at the token endpoint with method none — no client secret. Code exchange returns an access token and a rotating refresh token.

Standards

Scopes

The authorization server issues a single scope: openApi, which grants access to the Open API surface and therefore to every MCP tool. There’s no read/write split. openApi is a single grant covering the whole surface, so a connection that can read can also write — see the one invariant for what the tool boundary does and doesn’t enforce. What a scope never does is widen what a person can do. Authorization runs unchanged underneath every call: a token cannot touch a record its user could not touch in the CRM itself, and the denial surfaces as the same 403 a direct REST request would return.

Registering a client

Applications are registered by hand in the Lofty vendor portal, which issues a clientId. Public clients get no secret — PKCE replaces the client secret, but not the client id, which is still required on every authorize request.

Permissions and rate limits

A tool call is authenticated and authorized exactly like a direct call to the endpoint it resolves to:
  • It runs as the caller identified by the token, with that caller’s existing permissions. An operation the caller couldn’t perform through the CRM directly (or through the REST API) is refused here too, with the same error.
  • It’s subject to the same rate limits as a direct REST call to that endpoint — using MCP doesn’t grant a separate quota.

Invalid or missing credentials

If the credential is missing, expired, or doesn’t resolve to a real user or application, a tool call surfaces the underlying API’s own error rather than a generic MCP failure — for example:
See Error Codes for what each code means.