Authentication
@techwriter/sdk-core AuthAuthentication
Every TechWriter API call must be authenticated. The platform supports four mechanisms — API keys, OAuth 2.0 Client Credentials, OAuth 2.0 Authorization Code, and signed JWT Bearer tokens — and the SDK speaks all four with a consistent surface.
For most server-side workloads an API key is enough. If you act on behalf of users, ship a public app, or need short-lived credentials with audit trails, use OAuth 2.0. Whatever you pick, send the credential in the Authorization: Bearer … header — the legacy X-API-KEY header is still accepted for compatibility but is no longer recommended.
All authenticated requests must travel over HTTPS. Plain HTTP and self-signed certificates are rejected at the edge — there are no exceptions, including for sandbox traffic.
Authentication methods
Pick the mechanism that matches who is making the call and how long you can hold a credential.
API key types
The prefix tells you which environment a key targets. The SDK never mixes traffic across modes.
tw_test_…Test modeTargets the sandbox database. No real publishing happens and usage is not rate-limited or billed. Safe to check into version control for local development fixtures.tw_live_…Live modeTargets production. Treat these like production database credentials — never commit, never ship in client code.tw_restricted_…RestrictedLive key with a custom subset of scopes. Use these to give read-only dashboards or scoped automation just enough access.Available scopes
Restricted keys and OAuth tokens carry one or more scopes. Keep them as narrow as possible — leak blast radius scales with what a credential can do.
articles:readList, retrieve, and search articles. No write access.articles:writeCreate, update, publish, and archive articles.templates:readBrowse the template library and folder hierarchy.templates:writeCreate, edit, and delete templates and folders.users:readList users, groups, and role assignments.users:writeInvite users, edit profiles, assign roles and groups.webhooks:manageSubscribe, verify, and rotate signing secrets for webhooks.audit:readRead the immutable audit log for compliance reporting.Token lifecycle
The SDK handles caching, refresh, and retries automatically. The table below describes what happens at each stage so you can reason about edge cases.
Authentication errors
Auth failures always include a stable error.code in the body — branch on the code, not the message.
unauthorizedHeader missing, malformed, or token not recognized.Confirm Authorization: Bearer <token> is set and the key has not been revoked.token_expiredAccess token is past its exp time.Refresh the token and retry the request once.token_revokedKey was rotated or revoked in the dashboard.Re-authenticate with the new credentials.forbiddenToken is valid but the scope does not cover this endpoint.Check the requiredScope field in the error body and grant it on the key.ip_restrictedRequest came from an IP outside the key’s allowlist.Update the key’s IP allowlist or call from an approved range.authentication_timeoutThe session reached the idle timeout for interactive OAuth flows.Restart the OAuth authorization flow to obtain fresh tokens.rate_limitedToo many auth attempts in a short window.Honor the Retry-After header. The SDK does this automatically.Security best practices
The single biggest source of API key incidents is accidental commits. The rules below cost a few minutes each and prevent the painful ones.
Where to go next
1. Authenticate with an API key
import { TechWriterClient } from ;
"color: ">#8b949e">// Read the key from the environment — never hard-code it.
const tw = new TechWriterClient({
apiKey: process.env.TECHWRITER_API_KEY
});
const articles = await tw.articles.list();2. OAuth 2.0 client credentials
import { TokenManager } from ;
const tokens = new TokenManager({
clientId: process.env.TW_CLIENT_ID,
clientSecret: process.env.TW_CLIENT_SECRET,
scope: [, ]
});
"color: ">#8b949e">// TokenManager caches and refreshes the token automatically.
const accessToken = await tokens.getAccessToken();3. Refresh tokens
"color: ">#8b949e">// The SDK auto-refreshes 60 seconds before expiry.
"color: ">#8b949e">// You can also force a refresh manually:
const fresh = await tokens.refresh();
console.log(, fresh.expiresAt);Rotation pattern
Generate the new key first, deploy it alongside the old one, then revoke the old key. The dashboard supports a 24-hour grace period where both keys are valid — long enough to roll a fleet without downtime.