Skip to main content
OAuth 2.0 is the recommended authentication method for multi-tenant integrations. Lofty supports three grant types:
The first two are served by https://crm.lofty.com/api/user-web/oauth/token; Client Credentials is served by https://api.lofty.com/oauth/token. They differ in more than the host — see Choosing between them.

Prerequisites

You need a Developer Platform account and a registered application. Sign up at the Lofty Developer Portal.

Authorization Code flow

1

Register your application

Create a new application in the Developer Portal. Provide your app name, description, and redirect URI(s).New applications start in Development Mode — you can test the full OAuth flow without review.
2

Obtain credentials

After registration, you’ll receive a Client ID and Client Secret.
Never expose your Client Secret in client-side code, public repositories, or logs.
3

Request an access token

Exchange your credentials for an access token via the OAuth 2.0 authorization code flow.
The Authorization header uses HTTP Basic authentication: Base64-encode <CLIENT_ID>:<CLIENT_SECRET> to produce the credential string.For complete token endpoint details, see the OAuth 2.0 API Reference.
4

Authenticate requests

Pass the access token in the Authorization header:

PKCE flow

For SPAs and native apps that cannot securely store a client secret. Uses a code verifier/challenge instead.
No client_secret is required. The Lofty CLI uses this flow for interactive browser login (lofty-cli auth login-browser).

Client Credentials flow

For server-to-server integrations where there is no browser to send a user to. Instead of a user approving your app, the account holder creates an API Key in their Lofty CRM (Settings → Integrations → API Keys) and gives it to you. You exchange it, together with your app credentials, for a short-lived access token.
This endpoint is not the one the other two flows use. Different host, JSON body instead of form fields, and credentials in the body instead of an Authorization header. Sending one flow’s request shape to the other endpoint fails with a message that does not point at the mismatch.
A successful response:
The token is prefixed oat_, lasts 2 hours, and carries no refresh token — mint a new one when it expires. Send it as Authorization: Bearer <ACCESS_TOKEN>, the same as any other access token.
The token’s scope comes from the API Key, not from your app. An exchanged token can reach exactly the endpoints the account holder selected when creating their key. Permissions your app is registered for but the key does not carry are refused; permissions the key carries are reachable whether or not your app lists them.So an integration can be configured correctly on the Developer Portal and still get 403 on every call, simply because the key it was given is narrower. When a call is refused, check the key’s permissions first.

Choosing between them

Permission scopes

Calling an endpoint a token is not scoped for returns HTTP 403. The body differs by grant type, because the two are checked against different records:
Both mean the same thing — the call is outside the token’s scope — but they point at different places to fix it. See Error codes.
Adding scopes is a breaking change. When you add new permission scopes to a production app, all existing tokens are invalidated (authorized_api_ids changes). Existing users must re-authorize your app. Always notify users before adding scopes.

App lifecycle

Updating a production app

Once in production, edits require review before taking effect. Your app continues operating with the current approved configuration during review. Non-breaking changes — app name, description, redirect URIs, removing scopes. Existing connections are unaffected. Breaking changes — adding new permission scopes invalidates existing tokens. Users must re-authorize. Notify users before submitting.
No. Edit controls are locked during review. Cancel the pending edit first if you need to make urgent changes.
Your app continues operating with its current configuration. You’ll receive the decline reason via email and can resubmit after making adjustments.