AuthenticationScopes & permissions

Scopes & permissions

Read/write scopes per domain, umbrella aliases, admin scopes, and how to pick what your integration needs.

Scopes are strings that declare exactly what your integration is allowed to do — think of them as a checklist of permissions. When you create an API key or register an OAuth client, you pick the scopes you need. Every API call Zoop receives is checked against those scopes, and calls that need a scope you didn't request are rejected.

How scopes work

Each scope is a string in the format verb:resource. There are two verbs:

  • read:* — fetch or list data
  • write:* — create, update, or delete data

Write access does not imply read access. If your integration needs to update a customer and also fetch that customer back, request both write:customers and read:customers.

Admin scopes follow a different pattern (admin:*) and are covered below.

Scope list

The table below lists every public scope. The "consent screen label" column shows the exact text a Zoop user sees on the authorization screen when they approve your OAuth connection — keep these labels in mind when deciding which scopes to request, because users see them.

ScopeConsent screen label
read:customersView customers, contacts, and locations
write:customersCreate and edit customers, contacts, and locations
read:catalogView service catalog and pricing
write:catalogManage service catalog and pricing
read:catalog_itemsView catalog items
write:catalog_itemsCreate and edit catalog items
read:catalog_categoriesView catalog categories
write:catalog_categoriesCreate and edit catalog categories
read:quotesView quotes
write:quotesCreate and edit quotes
read:estimatesView estimates
write:estimatesCreate and edit estimates
read:communicationsView messages and communication history
write:communicationsSend messages on your behalf
read:companiesView your business profile
write:companiesEdit your business settings
read:settingsView settings and configuration
write:settingsEdit settings and configuration
read:invoicesView invoices and payment history
write:invoicesCreate and edit invoices
read:jobsView jobs and job history
write:jobsCreate and edit jobs
read:job_seriesView recurring job series
write:job_seriesCreate and edit recurring job series
read:plansView service plans
write:plansCreate and edit service plans
read:tax_ratesView tax rates
write:tax_ratesCreate and edit tax rates
read:notesView notes
write:notesCreate and edit notes
read:agent_sessionsView AI agent session history
write:agent_sessionsRun AI agent sessions on your behalf

Umbrella scopes

Two scopes are shortcuts that expand into multiple child scopes automatically. You can request either the umbrella scope or the individual child scopes — the effect on your token is identical.

Catalog umbrella

read:catalog expands to read:catalog_items + read:catalog_categories.
write:catalog expands to write:catalog_items + write:catalog_categories.

Request read:catalog if your integration needs to browse the full service catalog. Request read:catalog_items or read:catalog_categories alone if you only need one sub-resource.

# Requesting the umbrella — gives access to both sub-resources
scope=read:catalog

# Requesting only one sub-resource
scope=read:catalog_items

Estimates — legacy alias for quotes

Zoop renamed "estimates" to "quotes" in May 2026. The read:estimates and write:estimates scopes still work and expand to read:quotes and write:quotes respectively. They exist so tokens minted before the rename continue to work without reauthorization.

New integrations should request read:quotes / write:quotes directly. The estimates aliases are kept for backward compatibility but are not the preferred form.

Legacy scopeExpands to
read:estimatesread:quotes
write:estimateswrite:quotes

Sub-resources under customers

Contacts, locations, and tags are sub-resources of a customer. They share the customer scopes rather than having their own:

  • To list or create contacts for a customer, your token needs read:customers or write:customers.
  • The same applies to service locations and customer tags.

Notes are different. Notes have their own scope pair (read:notes / write:notes) and are independent of read:customers. Either an API key or an OAuth token that holds these scopes can use the notes endpoints.

There is one important restriction on note writes: creating, updating, or archiving a note requires a user-actor token (that is, an OAuth token or a user-actor API key), because every note change is attributed to the specific user who made it. A standard tenant-actor API key can read notes but cannot create or change them.

Admin scopes

Admin scopes grant elevated access to sensitive account-level operations. They can only be requested by integrations authorized by the tenant owner — office and technician roles cannot create tokens that include admin scopes.

Request admin scopes only when strictly necessary. Most integrations do not need them.

ScopeWhat it grants
admin:tenantManage team members and tenant settings
admin:billingAccess billing and subscription info
admin:credentialsManage API keys and OAuth clients

admin:credentials is required to create or revoke API keys via the API. The external access endpoints (/api/external-access) enforce this scope.

User-actor vs tenant-actor

Every authenticated request in Zoop runs as one of two "actor" types. This affects which scopes you can actually receive.

  • User-actor — the token represents a specific human user (owner, office staff, or technician) who clicked "Authorize" in your OAuth flow. The scopes your token receives are capped by that user's role. For example, a technician-role user cannot authorize admin:tenant even if your client requests it — Zoop silently drops scopes the user's role doesn't allow.
  • Tenant-actor — an API key that acts on behalf of the business as a whole, not tied to any individual user. The scopes are exactly what you set when creating the key.

In short: OAuth gives you user-actor tokens, and API keys give you tenant-actor tokens.

See OAuth and API keys for setup details.

Requesting scopes

Pass your chosen scopes as a space-separated list in the scope parameter. The two tabs below show where that parameter goes for each auth method.

GET /oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.example.com/callback
  &response_type=code
  &scope=read:customers write:customers read:jobs
  &state=RANDOM_STATE_VALUE

Choosing the right scopes

Request only the scopes your integration actually uses. Fewer scopes means less damage if a token is ever leaked, and users are more likely to approve a short, focused consent screen than a long one.

A typical read-only reporting integration needs:

read:customers read:jobs read:invoices read:quotes

A full-service scheduling integration might need:

read:customers write:customers read:jobs write:jobs read:catalog read:quotes write:quotes