Skip to main content
Worktruck.app accepts three credential types. Every request must include one. If none is present, the API returns 402 Payment Required with payment options (for x402) or 401 Unauthorized with a WWW-Authenticate challenge (for OAuth discovery).

API keys (developers)

Pass your key in the Authorization header:
Authorization: Bearer bsk_live_<key>

Key format

EnvironmentPrefixExample
Productionbsk_live_bsk_live_a1B2c3D4...
Testbsk_test_bsk_test_x9Y8z7W6...
Keys are 52 characters total: 9-character prefix + 43 random alphanumeric characters.

Key management

OperationEndpointMethod
Create key/api/v1/api-keysPOST
List keys/api/v1/api-keysGET
Get key/api/v1/api-keys/{id}GET
Rotate key/api/v1/api-keys/{id}/rotatePOST
Revoke key/api/v1/api-keys/{id}DELETE

Key rotation

Rotate a key to get a new secret while preserving the key’s metadata, scopes, and audit trail. The old key is immediately revoked and a new one is returned.
curl -X POST https://api.worktruck.app/api/v1/api-keys/{id}/rotate \
  -H "Authorization: Bearer bsk_live_your_key_here"
The response includes the new raw key. Store it immediately — it cannot be retrieved again.

Scopes

Keys can be scoped to limit access. A key with null scopes has full access. Scoped keys use the format domain:action:
{
  "name": "Read-only contacts",
  "scopes": ["contacts:read", "crm:read"]
}
If a request requires a scope the key doesn’t have, the API returns 403 Forbidden.

Key security

  • Keys are hashed with Argon2id (memory-hard) before storage, with a server-side pepper on the deterministic lookup index. The raw key is never persisted.
  • Keys are shown once at creation. They cannot be retrieved again.
  • Revoked keys are immediately unusable.
  • Key usage is tracked via last_used_at.
  • All key operations are recorded in the audit log.

Keycloak OIDC (OAuth clients)

Claude.ai’s custom-connector UI, and any other OAuth 2.1 MCP client, authenticates through Keycloak at auth.builddaddy.app/realms/worktruck. You don’t set up an OAuth client yourself — Claude.ai uses RFC 7591 Dynamic Client Registration to register with Keycloak on first use, runs the PKCE authorization-code flow in a browser popup, and presents the resulting JWT on every MCP request. From your side, the flow is:
  1. Paste https://mcp.worktruck.app/mcp/v1 into Claude.ai’s custom connector URL field.
  2. Claude.ai’s first request to the server returns 401 Unauthorized with a WWW-Authenticate: Bearer resource_metadata="..." header pointing at /.well-known/oauth-protected-resource.
  3. Claude.ai fetches that document, discovers Keycloak as the authorization server, registers itself, and redirects you to Keycloak login.
  4. After you sign in, Keycloak issues a JWT with aud=mcp (or aud=https://mcp.worktruck.app/mcp/v1 under RFC 8707 resource binding). Claude.ai presents it on subsequent MCP requests.
Worktruck validates the JWT against the realm’s JWKS, maps the sub claim to your Worktruck tenant and member via the internal idp_users table (JIT-provisioning a new tenant on first ever login), and enforces Mcp-Protocol-Version: 2025-06-18 on every non-initialize JWT-authenticated request. Tokens carry the mcp:tools scope. Domain-level access (contacts:read vs. tasks:write, etc.) is enforced by your member’s access policies, not by token scopes.

x402 payments (agents)

AI agents can pay per-request with USDC on Base. No account, no API key required. Pass the x402 payment receipt in the PAYMENT-SIGNATURE header:
PAYMENT-SIGNATURE: <x402 receipt>
The first payment from a new wallet auto-provisions a tenant. See x402 payments for the full protocol.

Error responses

StatusMeaning
401 UnauthorizedInvalid, expired, or revoked API key; invalid/expired JWT; missing Mcp-Protocol-Version on JWT-authenticated MCP request. Response includes WWW-Authenticate header for OAuth discovery
402 Payment RequiredNo credentials provided — includes payment options in response
403 ForbiddenValid key/token, but missing required scope or member access