Pick the one that matches where your code runs.
A typed API client, token verifier and local authorizer. Requires Node 18 or later, and runs anywhere fetch exists.
A module and guards, so authorization is a decorator rather than a call in every handler.
Signs a single-page app with no backend in through Hosted Login, with tokens kept in memory.
Tokens are verified against the published keys, and permission checks are answered from cached grants, so a check normally costs no network call.
@UseGuards(CanopyTokenGuard, CanopyGuard)
@RequirePermission("invoice.approve", { scope: "org" })
@Post("invoices/:id/approve")
approve() {}The parts of an integration that are easy to get subtly wrong.
Every operation's types come from the published OpenAPI document.
Error codes you can branch on, with helpers that map failures to the right status.
Built into the client, with one paginator over every list.
Signatures checked in constant time, with stale timestamps refused.
Pins the algorithm, and checks the audience and token type.
The local authorizer keeps its cache fresh, so a change you make reaches your checks without a redeploy.
Signed events tell your service what changed.
An ordered feed for catching up after downtime.
There's no SDK for other languages yet. The API is the supported route.
Generate a client from the published documents.
The same operations the SDKs call.
Test cases to prove your own evaluator matches Canopy's.