Scopes
A scope names one kind of access. API keys and registered apps carry scope lists, and every endpoint that reads or
changes data needs one. A call without the scope gets 403 insufficient_scope; detail names the missing scope.
Vocabulary
read:projects/write:projectsread:products/write:productsread:vendors/write:vendorsread:labor/write:laborread:estimates/write:estimatesread:assessments/write:assessmentsread:bids/write:bidsread:quotes/write:quotesread:files/write:filesread:conversations/write:conversationsread:contacts/write:contactsread:webhooks/write:webhooksread:agents/write:agentsread:calls/write:callsread:appointments/write:appointmentsread:pricebook/write:pricebookread:phone-numbers/write:phone-numbersread:campaigns/write:campaignsread:consent/write:consentread:integrations/write:integrationsread:usage: the company's AI usage (GET /v1/usage). An app reads only its own usage.admin:org: implies every other scope in the key's company. Use sparingly. An app can never ask for it.*: every scope, including scopes added later.
Only a key that works in its own company (This company) can hold admin:org or *. See
Company scope.
Archiving a resource needs that resource's write scope: write:projects for projects and pages, write:products
for products and lists, write:vendors, write:labor. Disconnecting an integration needs write:integrations.
Widgets and custom properties are company setup: only an admin of the company, or a key with admin:org, can
create, change or remove them. An app is refused with 403 forbidden whatever its scopes; an admin can do it in
Exayard.
API keys
Every key belongs to an app, and a key's scopes are a subset of its app's. When you make a key you pick All of the
app's scopes (the default) or Specific ones. A key can never hold a scope its app does not ask for. The one
exception is admin:org or * on a This company key, as above.
A call made with a key is checked against the key's own scopes and against what its app holds in that company. So removing a scope from the app also takes it from every key of that app. See Apps and keys.
Older ak_ keys hold exactly the scopes picked when they were made.
Registered apps: scopes per install
An app lists the scopes it asks for when it is registered (any scope except admin:org). Each company that installs
it grants those scopes to its own install, and the app's calls in that company are checked against that grant. For an
app, the 403 detail says the install in this company does not grant the scope, and that an admin of the company can
approve it on the Developer page.
- Adding scopes to your app does not change existing installs. Each company keeps its current grant until an admin approves the new access on its Connected apps row. Your owner company gets the new scopes at once.
- Removing scopes from your app removes them from every install at once. A call already in flight under the old
grant is retried once; if it relied on a removed scope, it gets
insufficient_scope. - Calls that name no company (
GET /v1/me,GET /v1/installations, and the company calls on/v1/organizationsin Accounts for your customers) hold no company scopes.
Project-limited installs
When an admin installs an app, they choose All projects or Only these projects (1 to 500 of the company's projects). They can change the choice later by installing again. With a project list:
- Listing projects returns only the listed ones.
- Reading, updating and archiving a listed project works, and so do its pages, files and symbols, and search within it. A project outside the list, or a file in no project, is refused, mostly as not found.
- Operations that act on the whole company, rather than on one project, are refused with 403
forbidden.
Session tokens and personal connections
The Exayard web app's own session, and OAuth tokens from clients that are not registered apps (personal connections such as ChatGPT, Claude or Cursor), are not checked against scopes. They act with the permissions of the person who signed in, in that person's companies. See Personal connections.
MCP
On the MCP server every tool needs a scope. A tool that mirrors a REST endpoint needs that endpoint's scope. A
registered app sees and can call only the tools its install grants. A This company key acts in its own company
without naming it. Any other app call names its company with the Exayard-Organization-Id header or an
organizationId argument. Tools that only a person may use are never available to apps.