Skip to main content

Authentication

The SDK authenticates every request with an OAuth 2.0 bearer token. You choose how that token is obtained when you create the client (or bring one yourself via the OAuth 2.0 endpoints). Configure auth once; the SDK applies it — and, where the flow allows, refreshes it — for every request.

Choosing a flow

FlowUse it forClient secretSDK config
Authorization Code + PKCEInteractive apps acting as a user — SPAs, CLIs, mobile/desktopNorefreshToken (or bearer)
Client credentialsConfidential server-to-server machine accessYesclientCredentials
Password grantFirst-party scripts / quick devNopassword
Bearer tokenA token you already holdbearer

If your software acts on behalf of a human who logs in, use Authorization Code + PKCE. For an unattended backend, client credentials is the long-term answer (see the availability note below); until it ships, a password grant is the simplest first-party option.

Authorization Code + PKCE

The modern, secure flow for public clients (RFC 7636) — no client secret is ever stored. The user authenticates with babelforce and approves your app; you then exchange the returned code (bound to a one-time PKCE verifier) for an access token and a rotating refresh token. The SDK ships helpers for each step (pkceChallenge / GeneratePKCE, buildAuthorizeUrl / BuildAuthorizeURL, and the authorization-code exchange).

// 1. Generate a PKCE verifier/challenge and send the user to the consent page.
const { codeVerifier, codeChallenge } = await pkceChallenge();
const consentUrl = buildAuthorizeUrl({
baseUrl: "https://services.babelforce.com",
clientId: "your-public-client-id",
redirectUri: "https://app.example.com/callback",
scope: "*",
codeChallenge,
state: "csrf-token",
});
// Redirect the user to `consentUrl`; they return to redirectUri?code=…&state=…

// 2. Exchange the code (with the same codeVerifier) for tokens.
const tokens = await authorizationCodeGrant({
baseUrl: "https://services.babelforce.com",
code: "code-from-the-redirect",
redirectUri: "https://app.example.com/callback",
clientId: "your-public-client-id",
codeVerifier,
});

// 3a. Long-lived client — the access token refreshes transparently (refresh tokens rotate):
const mgr = await ManagerClient.connect({
auth: { kind: "refreshToken", refreshToken: tokens.refresh_token!, clientId: "your-public-client-id" },
});
// 3b. …or a one-shot client straight from the access token:
// const mgr = await ManagerClient.connect({ auth: { kind: "bearer", token: tokens.access_token } });

Client credentials

An OAuth2 client_credentials grant for confidential, server-to-server access: the SDK exchanges your clientId / clientSecret for a bearer token at /oauth/token and applies it to every request. The token is refreshed transparently before it expires in all three languages.

Limited availability

Issuing client_id / client_secret pairs (via OAuth2 applications) is currently in security review and not yet generally available. Until it ships, prefer Authorization Code + PKCE for user-facing apps, or the password grant for first-party scripts. Treat any client secret as highly sensitive — never commit it or expose it to a browser/mobile client.

const mgr = await ManagerClient.connect({
auth: { kind: "clientCredentials", clientId, clientSecret },
});

Password grant (legacy)

A first-party grant kept for interactive/dev use — it sends a username/password to /oauth/token with the public manager client id (no secret). Prefer PKCE or client credentials for new integrations. The token refreshes transparently in all three languages.

const mgr = await ManagerClient.connect({ auth: { kind: "password", user, pass } });

Bearer token

If you already hold a valid access token — for example from the PKCE exchange above, or one minted elsewhere — pass it directly:

const mgr = await ManagerClient.connect({ auth: { kind: "bearer", token } });

OAuth 2.0 endpoints

The raw OAuth 2.0 endpoints — /oauth/authorize, /oauth/token, /oauth/revoke — are exposed as mgr.auth / mgr.Auth for when you manage tokens yourself. They authenticate via credentials carried in the request itself (per RFC 6749 / 7009), independent of the client's configured auth.

Token endpoint

Exchange a grant (authorization_code, refresh_token, password, or client_credentials) for an access token.

const tokens = await mgr.auth.token({
grant_type: "client_credentials",
client_id: "…",
client_secret: "…",
scope: "…",
});
console.log(tokens.access_token, tokens.expires_in);

Authorize & revoke

// Authorization-code consent/redirect (for PKCE, prefer buildAuthorizeUrl above):
await mgr.auth.authorize({
response_type: "code",
client_id: "…",
redirect_uri: "https://app.example.com/callback",
scope: "…",
});

// Revoke an access or refresh token (RFC 7009):
await mgr.auth.revoke({ token: "…" });

Grant failures

A failed grant — wrong credentials, an expired or already-used refresh token, an unavailable token endpoint — surfaces as the SDK's typed API error, whether the SDK fetched the token transparently or you called a grant helper yourself: ManagerApiError (status, code, body) in TypeScript, *manager.APIError (Status, Code, Message, Body; errors.As compatible) in Go, and ManagerError::Api { status, code, .. } in Rust. Branch on the structured status/code fields rather than parsing the error message.

Base URL

The SDK talks to https://services.babelforce.com by default. Set baseUrl (TypeScript) / BaseURL (Go) — or the builder's .base_url() (Rust) — to target a per-customer or non-production host:

const mgr = await ManagerClient.connect({
baseUrl: "https://acme.babelforce.com",
auth: { kind: "clientCredentials", clientId, clientSecret },
});

Reference