1. Docs
  2. AI Quickstart

AI Quickstart

Integrating Canopy with an AI coding agent? Point it at the machine-readable surfaces below, then walk the API from an empty Environment to a passing permission check.

Machine-readable surfaces

Point your agent at these. Everything the docs describe is also published in formats an agent can fetch directly, with no browser and no rendering:

/llms.txt: an index of every docs page and machine-readable resource on this site, in the llms.txt format./llms-full.txt: the same index plus the full endpoint catalog, authentication and response-envelope reference, and every webhook event type, in one fetch./openapi: the OpenAPI 3 documents behind this reference, covering the public API, portal & identity auth, OAuth/OIDC, and SCIM. Point a code generator at these to get a typed client./sitemap.xml: every page on the site, including one URL per documented API operation.
Don't guess documentation URLs

Endpoint pages live at /docs/api-reference/{operationId}, for example /docs/api-reference/ApiPermissionsController_evaluate. The ids come from the OpenAPI documents; resource-name URLs like /docs/api-reference/permissions do not exist.

Pick a session mode

The walkthrough below provisions an Environment over the API, which is a server-to-server job and needs no decision here. Signing your end users in from a browser does, and it is the one part that cannot be inferred from the endpoint catalog, because every mode calls the same endpoints:

Custom auth domain: recommended for a browser app on its own domain. Point a subdomain you control (auth.yourapp.com) at Canopy and call it instead of the platform origin. The refresh token's cookie is then first-party on your own site, so silent refresh works in every browser and you write no backend auth code. Set it up in the Console under Environment → Integrations → Custom Auth Domain. See Custom auth domain.Backend proxy (BFF): when DNS is out of your hands, when you already route API traffic through your own backend, or for native mobile, which has no useful cookie jar. Your backend holds the session. See Backend Proxy (BFF).Same-site: your app and the API origin are already the same site; nothing to do.
Decide this before you write sign-in code

This is worth deciding before you write sign-in code rather than after. Nothing here fails at build time: curl and a same-origin dev server behave perfectly. A third-party refresh cookie only breaks in a real browser on your production domain, where the user is signed out as soon as the 15-minute access token lapses.

Prerequisites

Provisioning starts in the Developer Console, where you create your credentials. Everything after these three steps can be driven over the API.

In the Console
Create an account and sign in to the Console.Create an Application. Its Environments are created with it, and every resource in this guide lives inside one Environment.Open the API Keys page and create a key for the Environment you are working in. The cnpy_-prefixed secret is shown exactly once. Store it as CANOPY_API_KEY.

API keys are Environment-scoped: a key created in Development can never touch Production. The full credential map (which integration scenario needs which credential) is on Keys & Credentials.

API walkthrough

This takes an empty Environment to a passing permission check. Every request goes to your API origin with the key in the X-API-Key header. Single-resource responses arrive as { "data": ... }, collections as { "items": [...] }, and errors as { "error": ... }, the same envelope on every endpoint. The steps use plain curl so they work from any language; on Node.js or NestJS, the official SDKs wrap the auth header, envelope, retries, and pagination for you.

1. Register your permission vocabulary

Permissions are free-form dot-notation keys your application checks for. Register them in batches:

curl -X POST https://auth.canopy-io.com/api/v1/permissions \
  -H "X-API-Key: $CANOPY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "permissions": [
      { "key": "invoice.read",    "description": "View invoices",    "category": "Invoices" },
      { "key": "invoice.approve", "description": "Approve invoices", "category": "Invoices" }
    ]
  }'
2. Create a role and attach permissions

Create the role first (its id comes back in data.id), then set the permission keys it grants:

curl -X POST https://auth.canopy-io.com/api/v1/roles \
  -H "X-API-Key: $CANOPY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Invoice Manager", "description": "Read and approve invoices" }'

curl -X PUT https://auth.canopy-io.com/api/v1/roles/$ROLE_ID/permissions \
  -H "X-API-Key: $CANOPY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "permission_keys": ["invoice.read", "invoice.approve"] }'
3. Create an identity

The end user being authorized. Keep the returned data.id:

curl -X POST https://auth.canopy-io.com/api/v1/identities \
  -H "X-API-Key: $CANOPY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "ada@acme.com", "first_name": "Ada", "last_name": "Lovelace" }'
4. Find the root hierarchy node

Every Environment starts with a root node, and assignments attach at a node. Fetch the tree and keep the root's id:

curl -H "X-API-Key: $CANOPY_API_KEY" https://auth.canopy-io.com/api/v1/nodes

# → { "data": { "tree": [ { "id": "<ROOT_NODE_ID>", ... } ] } }
5. Assign the role at the root

Assignments cascade to every descendant of their node, so assigning at the root grants the role everywhere, exactly what a flat-RBAC setup wants:

curl -X POST https://auth.canopy-io.com/api/v1/assignments \
  -H "X-API-Key: $CANOPY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "identity_id": "$IDENTITY_ID",
    "role_id": "$ROLE_ID",
    "node_id": "$ROOT_NODE_ID"
  }'
6. Evaluate: the question your app asks in production

scope: "app_wide" asks “does this identity hold the permission anywhere?”; scope: "node" with a node_id anchors the check to one part of the tree:

curl -X POST https://auth.canopy-io.com/api/v1/permissions/evaluate \
  -H "X-API-Key: $CANOPY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "identity_id": "$IDENTITY_ID",
    "permission": "invoice.approve",
    "scope": "app_wide"
  }'

# → {
#     "data": {
#       "allowed": true,
#       "permission": "invoice.approve",
#       "scope_evaluated": "app_wide",
#       "granting_roles": ["Invoice Manager"]
#     }
#   }
7. Optional: subscribe to change events

Webhooks fire on catalog event types: the strings must match the catalog verbatim, or use the wildcard "*". Fetch the full catalog live from GET /api/v1/webhooks/event-types, or read Webhook Event Types:

curl -X POST https://auth.canopy-io.com/api/v1/webhooks \
  -H "X-API-Key: $CANOPY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/access-changes",
    "event_types": ["assignment.created", "assignment.removed"]
  }'

That's the whole loop: vocabulary, role, identity, assignment, evaluation. From here, the API Reference documents every endpoint the specs enumerate, and Webhook Event Types lists every event string you can subscribe to.

Environment
API version
v1.0
On this page Was this page helpful?

Tell us how we can improve this guide.