Authentication
There are two token types. A PAT is the simplest way to script the REST API. OAuth 2.1 + PKCE is for MCP clients, which run the sign-in for you.
Personal Access Tokens
A PAT is a long-lived token (strac_pat_*) you create while signed in to Strac Comply. Anyone on your team can create one with read scopes. Write scopes need an owner or admin. We store only a SHA-256 hash, and you see the secret exactly once. PATs work on both /api/v1/* and the MCP endpoint /mcp, with the same scopes and the same revocation. For an AI agent that can open a browser (Claude Code, Codex, Cursor), OAuth below is the better fit.
Create a PAT
POST /api/companies/{companyId}/pats with your Cognito ID token (your signed-in session). Role: owner / admin (to mint write scopes).
Body (unknown keys are rejected)
| Field | Type | Description |
|---|---|---|
| labelrequired | string, 1–80 chars | Shows in the admin UI and the audit log. |
| scopesrequired | string[] (non-empty) | Least-privilege scope set; each must be a canonical scope. |
| expiresInDaysrequired | integer | Token lifetime in days. 0 = never expires (service accounts).03090365 |
Request:
curl -X POST 'https://comply.strac.io/api/companies/comp_demo/pats' \ -H 'Authorization: Bearer eyJraWQ...<cognito-id-token>' \ -H 'Content-Type: application/json' \ -d '{ "label": "CI deploy bot", "scopes": [ "compliance:read", "documents:write" ], "expiresInDays": 90}'Response:
{ "success": true, "data": { "token": "strac_pat_xxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxx", "pat": { "patId": "<sha256-hash>", "prefix": "strac_pat_a1b2", "label": "CI deploy bot", "scope": "compliance:read documents:write", "expiresAt": 1787616000, "email": "ci@example.com", "createdAt": "2026-05-27T08:18:14.536Z", "createdBy": "ci@example.com", "lastUsedAt": null, "revokedAt": null, "status": "active" } }}The secret is shown once
token field is returned once, when you create the PAT, and can't be recovered later. We keep only its hash. Save it right away, for example in your CI secret store.Using a PAT
Send it as a bearer token to the v1 base URL. The companyId in the path is checked against the token's company. A request for another company is refused.
curl 'https://comply.strac.io/api/v1/companies/comp_demo/controls' \ -H 'Authorization: Bearer strac_pat_xxxxxxxxxxxx'List and revoke
GET /api/companies/{companyId}/pats lists token metadata (prefix, label, scope, status, expiry, last-used), never the secret. POST /api/companies/{companyId}/pats/{patId}/revoke revokes it right away, with no grace period. An optional reason lands in the audit log.
OAuth 2.1 + PKCE (MCP)
The MCP server speaks OAuth 2.1 with PKCE. Access tokens are mcp_at_* and last 7 days. Refresh tokens are mcp_rt_* and rotate on every use, with a sliding 30-day window. You sign in once and stay signed in while you keep using the client. Only a full month without use asks you to sign in again. MCP clients like Claude Code, Codex, Cursor and the official SDK run the whole flow for you, so you usually never touch the endpoints below.
Discovery handshake
A client that follows the MCP spec needs no hard-coded URLs. It finds them like this:
- Unauthenticated
POST /mcp→401with aresource_metadatapointer. - Fetch protected-resource metadata (RFC 9728) at
/.well-known/oauth-protected-resource; readauthorization_servers[0]. - Fetch authorization-server metadata (RFC 8414) for the authorize / token / registration endpoints.
- Dynamic-register (RFC 7591), open the browser at the authorize endpoint → consent on
comply.strac.io→ exchange the code formcp_at_*.
Dynamic client registration
curl -X POST 'https://mcp.comply.strac.io/oauth/register' \ -H 'Content-Type: application/json' \ -d '{ "client_name": "My MCP Client", "redirect_uris": ["http://127.0.0.1:8765/callback"], "grant_types": ["authorization_code", "refresh_token"], "scope": "compliance:read" }'Redirect URI rules
http://127.0.0.1:*, http://localhost:* or http://[::1]:*, on any port. An https:// callback is allowed only on the hosted AI clients we trust (such as claude.ai, chatgpt.com, cursor.com and vscode.dev). Registration refuses any other https host, and custom schemes like file: or app:, so a stranger can't receive a sign-in meant for you.PAT or OAuth?
Scripting the REST API from CI, a cron or a backend job? Use a PAT. Connecting an AI agent like Claude Code, Codex or Cursor? Use OAuth, which the agent runs for you. See the MCP page for the connect steps for each agent.