References

Snap-in scopes

Snap-ins support scopes—a permissions framework that controls exactly what a snap-in's service account can access during execution. Instead of granting broad system-level permissions, scopes let you declare the minimum set of permissions your snap-in needs, improving security and governance across your DevRev environment.

Every snap-in must declare the specific permissions it requires in its manifest file. These permissions are granted to the service account at installation time, and the snap-in can only access what it has been explicitly allowed.

When installing a snap-in, users are prompted to review and grant the permissions the snap-in requests. Installation proceeds only after all required permissions have been accepted.


Scope format

Each scope follows an object:permission syntax. You specify the object type you need access to, followed by a colon, followed by the permission level.

Permission levels

Most objects support three standard permission levels:

ScopeWhat it grants
object:readRead-only access (get, list, count)
object:writeRead, create, and update access
object:allFull access — read, create, update, and delete

Some objects use more granular permissions like object:update (grants create and update but not broader write access). When in doubt, refer to the API-to-scope reference.

Examples

ScopeMeaning
ticket:readRead-only access to tickets
ticket:writeRead, create, and update tickets
rev_user:writeRead, create, and update customer details
article:updateRead and update articles
conversation:readRead access to conversations
command:writeCreate and update commands
tag:writeCreate or modify tags

Add scopes to a snap-in

1. Identify the APIs your snap-in uses

Review your snap-in's code and identify all DevRev API calls it makes. For example, if your snap-in creates timeline entries and updates customers, note the endpoints: timeline-entries.create, rev-users.get, rev-users.update.

2. Determine the required scopes

Map each API endpoint to its corresponding scope using these general rules:

  • GET/list operationsobject:read
  • Create and update operationsobject:write
  • Delete operationsobject:all

For timeline-entries.create and timeline-entries.update, the required scope is the parent object's read permission — if the timeline entry belongs to an issue, you need issue:read; if it belongs to a ticket, you need ticket:read.

Referenced DON IDs require read scope. Any DevRev object reference (DON ID) passed in a request payload requires the corresponding :read scope on that object type, in addition to the scope required for the operation itself.

For example, calling works.create to create an issue with a tags field that references existing tag DON IDs requires both:

  • issue:write — to create the issue
  • tag:read — to resolve and validate each tag DON ID passed in the payload

This applies to every endpoint and every field that accepts a DON ID — owners, parts, accounts, custom object references, and so on. Audit each request payload for DON ID fields and add a :read scope for every referenced object type.

Refer to the API-to-scope reference for the complete mapping.

3. Add scopes to the manifest

Declare the scopes in the service_account section of your snap-in's manifest file:

service_account:
  display_name: DevRev Bot
  scopes:
    self:
      - scope: conversation:read
        optional: false
        reason: "Allow read access to conversations."
      - scope: rev_user:write
        optional: false
        reason: "Allow read and update customer details."
      - scope: comment:write
        optional: false
        reason: "Allow creation and updating of timeline entries."

Each scope entry includes:

FieldDescription
scopeThe permission being requested, in object:permission format
optionalWhether the scope is required (false) or optional (true) for installation
reasonA human-readable explanation shown to users during installation

4. Publish your snap-in

The snap-in creation and draft process remains the same. On the UI, users see a prompt to explicitly grant the requested permissions while installing the snap-in. Installation proceeds only after all required permissions have been accepted.

5. Upgrade an existing snap-in

For existing snap-ins, add the scopes to the manifest and republish. The upgrade flow remains the same. For DevRev snap-ins, ensure the marketplace.yaml file is present alongside manifest.yaml.


Scope types: self vs. impersonate

Scopes are organized into two categories under the service_account section.

Self scopes

Self scopes define the permissions the service account has when operating on its own behalf. This is the most common type.

service_account:
  scopes:
    self:
      - scope: ticket:read
        optional: false
        reason: "Read ticket details."

Impersonate scopes

Impersonate scopes define the permissions the service account has when acting on behalf of another entity (a customer or user). The effective permissions are the intersection of the service account's impersonate scopes and the impersonated user's own permissions—so the snap-in can never exceed what the user themselves could do.

service_account:
  scopes:
    impersonate:
      - act_as: all_devusers
        scopes:
          - scope: ticket:read
            optional: false
            reason: "Read tickets on behalf of the user."

Scopes for manifest-defined objects

If your snap-in's manifest creates objects like commands, tags, imports, or dashboards, include the corresponding scopes as well, since these objects are created via the service account.

For example, if your manifest defines tags and commands:

service_account:
  display_name: Example Snap-in
  scopes:
    self:
      - scope: command:write
        reason: "For command creation."
      - scope: tag:write
        reason: "For tag creation."

tags:
  - name: exampleTag
    description: Example description

commands:
  - name: exampleCommand
    namespace: devrev
    description: Example description
    surfaces:
      - surface: discussions
        object_types:
          - snap_in
    usage_hint: ""
    function: init_category_import

Custom object scopes

For snap-ins that work with custom objects, scopes follow this format:

custom_object:<leaf_type>:<permission>

Example: custom_object:asset:read grants read access to the custom object type asset.

Custom object scopes are created automatically when a custom object is defined via the consumer.

For certain cases, you might need to allowlist a snap-in to bypass the custom object scopes requirement. Check the Manage allowlist exceptions section for more details.


Empty scopes

If your snap-in does not call any DevRev APIs and needs no permissions, declare empty scopes to indicate this explicitly:

service_account:
  display_name: DevRev Bot
  scopes:
    self:

This tells the platform that the service account intentionally requires no permissions.


Best practices

Know the default self-permissions. The snap-in service account has default permission to read and update itself. Any API calls targeting the snap-in itself (including event-sources and related APIs where the parent is the snap-in) work without explicitly setting scopes.

Do not add required scopes after the initial release. Adding new required scopes on an update can break the snap-in for users who haven't granted the new permission. If you need additional scopes later, add them as optional: true. Optional scopes are granted automatically, but this behavior may change—plan your scopes from the start.

Remove scopes on updates without restriction. Removing scopes on subsequent updates is supported.

Request only what you need. Follow the principle of least privilege. Requesting fewer permissions makes it easier for admins to approve your snap-in and reduces security risk.

Include clear reasons. The reason field is shown to users during installation. Write descriptions that explain why each permission is needed in plain language.


Allowlist exceptions

In some cases, the scopes framework cannot fully support a snap-in's requirements. For these, the snap-in can be added to the allowlist to bypass scopes and use the older systems group permissions.

Custom objects created during activation

If a snap-in creates a custom object during its activation hooks and also needs custom_object:<leaf_type>:<permission> scopes for that same object, a circular dependency exists. Because the object doesn't exist yet when scopes are evaluated, these snap-ins need to be added to the allowlist.

Impersonation with agent authorization

If a snap-in uses impersonation scopes with act_as and expects permissions to be the intersection of the user's and service account's permissions, it may need to be added to the allowlist until agent impersonation is fully rolled out.

If your snap-in falls into either of these categories, raise a ticket to request allowlisting by snap-in version or package slug.


API-to-scope reference

The table below maps commonly used APIs to their required scopes. For the complete auto-generated reference covering every public endpoint, see the API-to-scope reference.

Work items (tickets, issues, opportunities)

The works.* APIs require scopes for each work item type your snap-in interacts with.

APIRequired scopes
works.get, works.list, works.count, works.group, works.exportticket:read, issue:read, opportunity:read
works.create, works.updateticket:write, issue:write, opportunity:write
works.deleteticket:all, issue:all, opportunity:all

Accounts and workspaces

APIRequired scope
accounts.get, accounts.listaccount:read
accounts.create, accounts.updateaccount:write
rev-orgs.get, rev-orgs.listrev_org:read
rev-orgs.create, rev-orgs.updaterev_org:write

Users

APIRequired scope
rev-users.get, rev-users.listrev_user:read
rev-users.create, rev-users.update, rev-users.mergerev_user:write
rev-users.deleterev_user:all
dev-users.get, dev-users.listdev_user:read
dev-users.create, dev-users.updatedev_user:write

Conversations

APIRequired scope
conversations.get, conversations.listconversation:read
conversations.create, conversations.updateconversation:write

Timeline entries

Timeline entries require the parent object's read scope. If the entry belongs to a ticket, you need ticket:read; if it belongs to an issue, you need issue:read.

APIRequired scope
timeline-entries.create, .update, .get, .list, .delete<parent>:read

Articles

APIRequired scope
articles.get, articles.listarticle:read
articles.create, articles.updatearticle:update
articles.deletearticle:all

Tags and commands

APIRequired scope
tags.get, tags.listtag:read
tags.createtag:write
commands.getcommand:read
APIRequired scope
links.listlink:read
links.createlink:write
links.deletelink:all

Engagements and meetings

APIRequired scope
engagements.listengagement:read
engagements.create, engagements.updateengagement:write
engagements.deleteengagement:all
meetings.get, meetings.listmeeting:read
meetings.create, meetings.updatemeeting:write

Incidents

APIRequired scope
incidents.get, incidents.listincident:read
incidents.create, incidents.updateincident:write

Surveys

APIRequired scope
surveys.get, surveys.listsurvey:read
surveys.create, surveys.update, surveys.send, surveys.submitsurvey:write

Groups and roles

APIRequired scope
groups.get, groups.listgroup:read
groups.updategroup:update
groups.members.listgroup_membership:read, group:read
groups.members.add, groups.members.removegroup_membership:update, group:read
roles.listrole:read
roles.create, roles.apply, roles.updaterole:update

Artifacts and dashboards

APIRequired scope
artifacts.get, artifacts.download, artifacts.locateartifact:read
artifacts.prepareartifact:create
dashboards.get, dashboards.listdashboard:read
dashboards.create, dashboards.updatedashboard:write

Workflows

APIRequired scope
workflows.getworkflow:read
workflows.create, workflows.templates.instantiateworkflow:write
workflows.deleteworkflow:all

Custom objects

APIRequired scope
custom-objects.get, custom-objects.list, custom-objects.countcustom_object:<leaf_type>:read
custom-objects.create, custom-objects.updatecustom_object:<leaf_type>:write
custom-objects.deletecustom_object:<leaf_type>:all

Snap widgets

APIRequired scope
snap-widgets.get, snap-widgets.countparent:read, snap_widget:read
snap-widgets.create, snap-widgets.updateparent:read, snap_widget:write

APIs that require no scope

The following APIs do not require explicit scopes: schemas.aggregated.get, schemas.custom.list, schemas.stock.list, schemas.subtypes.list, stage-diagrams.list, stages.custom.get, stages.custom.list, states.custom.get, states.custom.list, snap-ins.get, snap-ins.update, event-sources.event.schedule, event-sources.schedule, event-sources.unschedule, and recommendations.* endpoints.


FAQ

Does my existing snap-in stop working? No. Previously published snap-ins are not affected. Scopes are only required when publishing a new snap-in or republishing an updated version.

What happens if I don't define scopes? Publishing is blocked. The platform validates the presence of scopes as part of the publishing process.

Can I change scopes after publishing? You can remove scopes. You can add new scopes as optional: true. Adding new required scopes after the initial release is not supported—it can break the snap-in for existing users.

What if my snap-in doesn't need any permissions? Use empty scopes (self: with no entries) to explicitly declare that no permissions are required.

How do custom object scopes work? Use the format custom_object:<leaf_type>:<permission>. For example, custom_object:asset:read. These scopes are created automatically when a custom object is defined.

Where can I find the full API-to-scope mapping? See the API-to-scope reference—it is auto-generated from the public OpenAPI spec and stays up to date with every spec change.

Last updated on