Authorization and scopes
The Picked API controls access with scopes. Every authenticated caller carries a set of scopes, and those scopes decide which operations the caller can do. A caller is either a user with a session or an API key. This guide covers the scopes, the roles, and how the API resolves a permission.
The format of a scope name
A scope has the form resource/action:
organization/read
organization_members/create
organization_projects/delete
- resource — a lowercase name. It uses an underscore between words, as in
organization_membersandorganization_api_keys. - action — one of
create,read,update, ordelete.
The GraphQL schema holds the scopes in the Scope enum. There they are uppercase
with an underscore between words, as in ORGANIZATION_READ and
ORGANIZATION_MEMBERS_CREATE. The two forms name the same scope.
Full scope list
These are the scopes:
Organization
| Scope | GraphQL Enum | Description |
|---|---|---|
organization/create | ORGANIZATION_CREATE | Create an organization |
organization/read | ORGANIZATION_READ | Read the detail of an organization |
organization/update | ORGANIZATION_UPDATE | Update the name, the slug, and the settings of an organization |
organization/delete | ORGANIZATION_DELETE | Delete an organization |
Organization members
| Scope | GraphQL Enum | Description |
|---|---|---|
organization_members/create | ORGANIZATION_MEMBERS_CREATE | Add a member to an organization |
organization_members/read | ORGANIZATION_MEMBERS_READ | Read the member list of an organization |
organization_members/update | ORGANIZATION_MEMBERS_UPDATE | Update the role of a member |
organization_members/delete | ORGANIZATION_MEMBERS_DELETE | Remove a member from an organization |
Organization invitations
| Scope | GraphQL Enum | Description |
|---|---|---|
organization_invitations/create | ORGANIZATION_INVITATIONS_CREATE | Send an invitation to join an organization |
organization_invitations/read | ORGANIZATION_INVITATIONS_READ | Read the invitations that wait for an answer |
organization_invitations/delete | ORGANIZATION_INVITATIONS_DELETE | Revoke an invitation that waits for an answer |
Organization projects
| Scope | GraphQL Enum | Description |
|---|---|---|
organization_projects/create | ORGANIZATION_PROJECTS_CREATE | Create a project |
organization_projects/read | ORGANIZATION_PROJECTS_READ | Read the detail of a project |
organization_projects/update | ORGANIZATION_PROJECTS_UPDATE | Update the settings of a project |
organization_projects/delete | ORGANIZATION_PROJECTS_DELETE | Delete a project |
A scope on content inside a project also gives organization_projects/read. The
workspace, integration, lead, action run, and report scopes all give it. They do
not give organization_projects/create, organization_projects/update, or
organization_projects/delete.
Organization API keys
| Scope | GraphQL Enum | Description |
|---|---|---|
organization_api_keys/create | ORGANIZATION_API_KEYS_CREATE | Create an API key |
organization_api_keys/read | ORGANIZATION_API_KEYS_READ | Read the API keys. This gives the prefix only, and not the full key. |
organization_api_keys/delete | ORGANIZATION_API_KEYS_DELETE | Revoke an API key |
Organization integrations
| Scope | GraphQL Enum | Description |
|---|---|---|
organization_integrations/create | ORGANIZATION_INTEGRATIONS_CREATE | Set up an integration |
organization_integrations/read | ORGANIZATION_INTEGRATIONS_READ | Read the options of an integration |
organization_integrations/update | ORGANIZATION_INTEGRATIONS_UPDATE | Change the settings of an integration |
organization_integrations/delete | ORGANIZATION_INTEGRATIONS_DELETE | Remove an integration |
Organization reports
| Scope | GraphQL Enum | Description |
|---|---|---|
organization_reports/create | ORGANIZATION_REPORTS_CREATE | Create a report |
organization_reports/read | ORGANIZATION_REPORTS_READ | Read a report |
organization_reports/update | ORGANIZATION_REPORTS_UPDATE | Update the settings of a report |
organization_reports/delete | ORGANIZATION_REPORTS_DELETE | Delete a report |
Roles
Each member of an organization holds one of two roles:
Owner
An owner has full control inside the organization. These are the default scopes of an owner:
- All
organization/*scopes (read,update,delete) - All
organization_members/*scopes - All
organization_invitations/*scopes organization_projects/read,organization_projects/update,organization_projects/delete- All
organization_api_keys/*scopes - All
organization_integrations/*scopes organization_reports/read
Member
A member can reach most things, but cannot delete the organization and cannot control another member. These are the default scopes of a member:
organization/read,organization/updateorganization_members/readorganization_invitations/readorganization_projects/read,organization_projects/update,organization_projects/delete- All
organization_api_keys/*scopes - All
organization_integrations/*scopes organization_reports/read
These are the differences between an owner and a member:
| Capability | Owner | Member |
|---|---|---|
| Delete the organization | Yes | No |
| Invite new members | Yes | No |
| Remove members | Yes | No |
| Update member roles | Yes | No |
| Revoke invitations | Yes | No |
| Control projects and integrations | Yes | Yes |
| Control API keys | Yes | Yes |
| Read reports | Yes | Yes |
How scopes are resolved
When an authenticated request reaches the API, the API resolves the scopes like this:
- A user with a session — the API finds the role of that caller in the target organization. It then gives the caller the default scopes of that role.
- A request with an API key — the API uses the scopes that the key received when somebody created it. Those scopes are always scopes of the user who created the key.
Most queries and mutations point at one organization. For those, the caller must hold
the scope inside that organization. For a root-level operation such as
organizationCreate, the API resolves the scope at the account level.
When the caller does not hold the scope that an operation needs, the API returns an
authorization error with the code FORBIDDEN. See Errors.
Operations and required scopes
This table gives the scope that each common operation needs:
Queries
| Query | Required Scope |
|---|---|
organization | organization/read |
organizations | organization/read |
project | organization_projects/read |
apiKeys | organization_api_keys/read |
shopifyWebhooks | organization_integrations/read |
shopifyMetafieldConfigs | organization_integrations/read |
report | organization_reports/read |
Mutations
| Mutation | Required Scope |
|---|---|
organizationCreate | organization/create |
organizationUpdate | organization/update |
organizationDelete | organization/delete |
organizationMemberInvite | organization_invitations/create |
organizationInvitationRevoke | organization_invitations/delete |
organizationMemberRemove | organization_members/delete |
organizationMemberRoleUpdate | organization_members/update |
projectCreate | organization_projects/create |
apiKeyCreate | organization_api_keys/create |
apiKeyRevoke | organization_api_keys/delete |
shopifyWebhookCreate | organization_integrations/create |
shopifyWebhookUpdate | organization_integrations/update |
shopifyWebhookDelete | organization_integrations/delete |
shopifyMetafieldConfigCreate | organization_integrations/create |
shopifyMetafieldConfigUpdate | organization_integrations/update |
shopifyMetafieldConfigDelete | organization_integrations/delete |
reportCreate | organization_reports/create |
reportUpdate | organization_reports/update |
reportDelete | organization_reports/delete |
Some mutations do not require organization-level scopes because they operate on the caller's own data:
| Mutation | Requirement |
|---|---|
sessionStart / sessionCreate / sessionRefresh | No authentication required |
accountCreate / accountVerifyEmail / accountResendVerification | No authentication required |
oauthAuthorize / oauthCallback | No authentication required |
magicLinkSend / magicLinkVerify | No authentication required |
passwordResetSend | No authentication required |
passwordUpdate | Authenticated session (no specific scope). Exempt from the MFA requirement, so a user can set a password before they add a factor. A user with a verified factor needs an AAL2 session. |
organizationInvitationAccept / organizationInvitationDecline | Authenticated session (no specific scope) |
mfaFactorEnroll / mfaChallengeCreate / mfaChallengeVerify / mfaFactorUnenroll | Authenticated session (no specific scope). Exempt from the MFA requirement, so a user can add a factor and verify it. |
userMfaReset needs the root-level scope users/reset_mfa (USERS_RESET_MFA). The
mutation removes every authenticator of a user and signs the user out everywhere, so
their next sign-in starts at the setup.
Read your scopes
Root-level scopes
The viewerScopes query returns the root-level scopes for the authenticated caller:
query {
viewerScopes
}Response:
{
"data": {
"viewerScopes": ["ORGANIZATION_CREATE"]
}
}Organization-level scopes
Each Organization object exposes a viewerScopes field that returns the scopes the caller has within that specific organization:
query {
organization(input: { slug: "my-company" }) {
id
name
viewerScopes
}
}Response:
{
"data": {
"organization": {
"id": "org_abc123",
"name": "My Company",
"viewerScopes": [
"ORGANIZATION_READ",
"ORGANIZATION_UPDATE",
"ORGANIZATION_MEMBERS_READ",
"ORGANIZATION_PROJECTS_READ",
"ORGANIZATION_PROJECTS_UPDATE",
"ORGANIZATION_PROJECTS_DELETE",
"ORGANIZATION_API_KEYS_CREATE",
"ORGANIZATION_API_KEYS_READ",
"ORGANIZATION_API_KEYS_DELETE",
"ORGANIZATION_INTEGRATIONS_CREATE",
"ORGANIZATION_INTEGRATIONS_READ",
"ORGANIZATION_INTEGRATIONS_UPDATE",
"ORGANIZATION_INTEGRATIONS_DELETE",
"ORGANIZATION_REPORTS_READ"
]
}
}
}Use this to build a UI that changes with the permissions of the caller. An example is
a Delete Organization button that the UI hides when the caller does not hold
ORGANIZATION_DELETE.
Related
- Authentication
- How to authenticate with an API key
- API keys — the dashboard surface.
