Authorization

Subscriber types & company scoping

A webhook subscription is owned by the access token that creates it, and the type of token determines which companies it covers:

Token typeCompanies covered
Company Developer tokenThe single company the token is linked to.
Firm Developer tokenAll companies belonging to the firm
OAuth application access tokenAll companies the OAuth application can access.

A subscription has a callback URL — which must be HTTPS — a list of events, and a signing secret. You can create several subscriptions — for example, different callback URLs for different events.


Scopes

To subscribe to an event, your token must hold a scope that grants read access to the underlying resource.

Each event page lists its accepted scopes; holding either the resource's :readonly or :all scope satisfies the requirement. This requirement is not enforced at subscription time: a subscription can be created for any recognized event regardless of your current scopes.

The check happens when an event fires: if your credential doesn't satisfy the scope requirement at that moment, the delivery is skipped.

Practically, this means:

  • A subscription created without the required scope is valid and will start receiving deliveries as soon as the credential obtains that scope.
  • For developer tokens, the access token must hold the scope, be non-revoked and unexpired
  • For OAuth applications, at least one active (non-revoked) access token with a non-expired refresh token for the relevant company must hold the scope.

For how tokens obtain scopes, see the Understand Scopes guide .


Authorization Flow

flowchart TD
    A([Event fires]) --> B{Subscription matches event?}
    B -- No --> Z([No delivery])
    B -- Yes --> C{Event has required scopes?}
    C -- No --> D([Delivery created ✓])
    C -- Yes --> E{Token type}
    E -- Developer token --> F{Token holds required scope?}
    F -- No --> G([Skipped — missing scope])
    F -- Yes --> H{Token revoked?}
    H -- Yes --> I([Skipped — token revoked])
    H -- No --> J{Token expired?}
    J -- No --> D
    J -- Yes, has refresh token --> D
    J -- Yes, no refresh token --> K([Skipped — token expired])
    E -- OAuth application --> L{"Active token for company holds scope?"}
    L -- No --> M([Skipped — application ineligible])
    L -- Yes --> D