@picked/client 0.0.101-next.2 → 0.0.101-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.md +34 -158
  2. package/dist/{api-AaQeg3Ij.cjs → api-9o_emCM5.cjs} +1 -1
  3. package/dist/{api-BlRFU0Fi.js → api-BbQt8aW3.js} +1 -1
  4. package/dist/cjs/index.js +2 -2
  5. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  6. package/dist/cjs/server/index.js +1 -1
  7. package/dist/esm/index.js +2 -2
  8. package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
  9. package/dist/esm/server/index.js +2 -2
  10. package/dist/{plugin-CVD2TnRC.cjs → plugin-I8_6ncy_.cjs} +1 -1
  11. package/dist/{plugin-DhznDG-h.js → plugin-uZJ45vK6.js} +2 -2
  12. package/dist/{preview-unavailable-xWLCr93y.cjs → preview-unavailable-BUNxTYLe.cjs} +1 -1
  13. package/dist/{preview-unavailable-mW4Pj3Ph.js → preview-unavailable-BYFD2a58.js} +1 -1
  14. package/dist/{provider-zag5m5GH.cjs → provider-Bzi_Kb-n.cjs} +1 -1
  15. package/dist/{provider-COb_V-yq.js → provider-CQKp0iUJ.js} +1 -1
  16. package/package.json +5 -5
  17. package/dist/docs/_root.css +0 -101
  18. package/dist/docs/explanation/conditions-and-the-logic-engine.md +0 -94
  19. package/dist/docs/explanation/content-references.md +0 -99
  20. package/dist/docs/explanation/feature-flag-allocation.md +0 -218
  21. package/dist/docs/explanation/how-picked-works.md +0 -124
  22. package/dist/docs/explanation/how-pickedql-works.md +0 -76
  23. package/dist/docs/explanation/pages-and-flows.md +0 -64
  24. package/dist/docs/explanation/the-content-model.md +0 -87
  25. package/dist/docs/explanation/the-two-apis.md +0 -68
  26. package/dist/docs/explanation/why-server-side-rendering.md +0 -76
  27. package/dist/docs/explanation/workspaces-and-versions.md +0 -71
  28. package/dist/docs/how-to/add-a-step-field-or-action.md +0 -43
  29. package/dist/docs/how-to/analytics/index.md +0 -316
  30. package/dist/docs/how-to/archive-or-delete-a-workspace.md +0 -46
  31. package/dist/docs/how-to/authenticate-the-cli.md +0 -101
  32. package/dist/docs/how-to/authenticate-with-a-magic-link.md +0 -47
  33. package/dist/docs/how-to/authenticate-with-a-password.md +0 -59
  34. package/dist/docs/how-to/authenticate-with-an-api-key.md +0 -51
  35. package/dist/docs/how-to/authenticate-with-oauth.md +0 -40
  36. package/dist/docs/how-to/build-a-flow.md +0 -93
  37. package/dist/docs/how-to/call-an-external-api-from-a-workflow.md +0 -102
  38. package/dist/docs/how-to/connect-the-mcp-server.md +0 -46
  39. package/dist/docs/how-to/create-a-content-entry.md +0 -48
  40. package/dist/docs/how-to/create-a-project.md +0 -29
  41. package/dist/docs/how-to/create-an-experience.md +0 -42
  42. package/dist/docs/how-to/create-and-revoke-an-api-key.md +0 -42
  43. package/dist/docs/how-to/debug-with-the-chrome-extension.md +0 -57
  44. package/dist/docs/how-to/define-a-page-layout.md +0 -46
  45. package/dist/docs/how-to/fill-and-publish-a-page.md +0 -66
  46. package/dist/docs/how-to/install-the-gtm-template.md +0 -84
  47. package/dist/docs/how-to/install-the-sdk.md +0 -93
  48. package/dist/docs/how-to/install-the-vite-plugin.md +0 -69
  49. package/dist/docs/how-to/invite-and-remove-members.md +0 -35
  50. package/dist/docs/how-to/point-one-entry-at-another.md +0 -61
  51. package/dist/docs/how-to/preview-a-workspace.md +0 -28
  52. package/dist/docs/how-to/publish-a-workspace.md +0 -30
  53. package/dist/docs/how-to/read-a-feature-flag.md +0 -113
  54. package/dist/docs/how-to/read-a-referenced-entry.md +0 -109
  55. package/dist/docs/how-to/register-a-component.md +0 -55
  56. package/dist/docs/how-to/register-an-action-handler.md +0 -85
  57. package/dist/docs/how-to/register-an-api-that-uses-oauth2.md +0 -107
  58. package/dist/docs/how-to/render-a-step-form.md +0 -131
  59. package/dist/docs/how-to/render-an-unpublished-preview.md +0 -41
  60. package/dist/docs/how-to/retry-a-failed-call-with-a-loop.md +0 -81
  61. package/dist/docs/how-to/reuse-a-section.md +0 -53
  62. package/dist/docs/how-to/reuse-a-step-field-or-action.md +0 -28
  63. package/dist/docs/how-to/roll-back-a-published-version.md +0 -26
  64. package/dist/docs/how-to/run-an-ab-test.md +0 -49
  65. package/dist/docs/how-to/run-code-on-a-form-submission.md +0 -125
  66. package/dist/docs/how-to/server-render-a-page.md +0 -81
  67. package/dist/docs/how-to/set-a-content-security-policy.md +0 -32
  68. package/dist/docs/how-to/set-up-mfa.md +0 -113
  69. package/dist/docs/how-to/switch-workspaces.md +0 -122
  70. package/dist/docs/how-to/upload-and-use-an-asset.mdx +0 -73
  71. package/dist/docs/how-to/validate-a-field.md +0 -52
  72. package/dist/docs/how-to/wait-for-an-action-response.md +0 -182
  73. package/dist/docs/how-to/write-a-condition.md +0 -45
  74. package/dist/docs/how-to/write-a-predicate.md +0 -60
  75. package/dist/docs/index.md +0 -59
  76. package/dist/docs/reference/dashboard/actions.mdx +0 -56
  77. package/dist/docs/reference/dashboard/api-keys.mdx +0 -38
  78. package/dist/docs/reference/dashboard/conditions.mdx +0 -42
  79. package/dist/docs/reference/dashboard/content/asset-library.mdx +0 -63
  80. package/dist/docs/reference/dashboard/content/blocks.mdx +0 -57
  81. package/dist/docs/reference/dashboard/content/content-entries.mdx +0 -95
  82. package/dist/docs/reference/dashboard/content/models.mdx +0 -108
  83. package/dist/docs/reference/dashboard/content/pages.mdx +0 -61
  84. package/dist/docs/reference/dashboard/experiences.mdx +0 -51
  85. package/dist/docs/reference/dashboard/external-apis.md +0 -169
  86. package/dist/docs/reference/dashboard/features.mdx +0 -154
  87. package/dist/docs/reference/dashboard/fields.mdx +0 -106
  88. package/dist/docs/reference/dashboard/flow-builder/canvas.mdx +0 -58
  89. package/dist/docs/reference/dashboard/flow-builder/condition-builder.md +0 -57
  90. package/dist/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +0 -72
  91. package/dist/docs/reference/dashboard/flow-builder/nodes.md +0 -63
  92. package/dist/docs/reference/dashboard/labels.md +0 -321
  93. package/dist/docs/reference/dashboard/lead-search.md +0 -224
  94. package/dist/docs/reference/dashboard/projects.mdx +0 -44
  95. package/dist/docs/reference/dashboard/reports.mdx +0 -43
  96. package/dist/docs/reference/dashboard/steps.mdx +0 -37
  97. package/dist/docs/reference/dashboard/team-management.md +0 -29
  98. package/dist/docs/reference/dashboard/workflow-runs.md +0 -142
  99. package/dist/docs/reference/dashboard/workflow-templates.md +0 -182
  100. package/dist/docs/reference/dashboard/workflow-test-runs.md +0 -77
  101. package/dist/docs/reference/dashboard/workspace-versioning.mdx +0 -30
  102. package/dist/docs/reference/dashboard/workspaces.mdx +0 -76
  103. package/dist/docs/reference/delivery-api/experience-content.md +0 -152
  104. package/dist/docs/reference/delivery-api/index.md +0 -45
  105. package/dist/docs/reference/delivery-api/preview-caching-crawling.md +0 -79
  106. package/dist/docs/reference/delivery-api/project-config.md +0 -65
  107. package/dist/docs/reference/delivery-api/workspace-schema.md +0 -107
  108. package/dist/docs/reference/glossary.md +0 -201
  109. package/dist/docs/reference/management-api/authentication.md +0 -87
  110. package/dist/docs/reference/management-api/authorization-and-scopes.md +0 -291
  111. package/dist/docs/reference/management-api/error-handling.md +0 -232
  112. package/dist/docs/reference/management-api/pagination.md +0 -192
  113. package/dist/docs/reference/pickedql/data-sources.md +0 -174
  114. package/dist/docs/reference/pickedql/dimensions.md +0 -103
  115. package/dist/docs/reference/pickedql/filtering.md +0 -64
  116. package/dist/docs/reference/pickedql/index.md +0 -18
  117. package/dist/docs/reference/pickedql/schema.md +0 -172
  118. package/dist/docs/reference/pickedql/virtual-functions.md +0 -248
  119. package/dist/docs/reference/sdk/actions.md +0 -154
  120. package/dist/docs/reference/sdk/analytics-events.md +0 -453
  121. package/dist/docs/reference/sdk/conditions.md +0 -147
  122. package/dist/docs/reference/sdk/content-security-policy.md +0 -21
  123. package/dist/docs/reference/sdk/content.md +0 -253
  124. package/dist/docs/reference/sdk/experiences.md +0 -51
  125. package/dist/docs/reference/sdk/features.md +0 -256
  126. package/dist/docs/reference/sdk/fields.md +0 -255
  127. package/dist/docs/reference/sdk/index.md +0 -68
  128. package/dist/docs/reference/sdk/plugins/create-experience.md +0 -123
  129. package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +0 -74
  130. package/dist/docs/reference/sdk/plugins/index.md +0 -29
  131. package/dist/docs/reference/sdk/plugins/window-object.md +0 -25
  132. package/dist/docs/reference/sdk/predicates.md +0 -43
  133. package/dist/docs/reference/sdk/ssr/index.md +0 -33
  134. package/dist/docs/reference/sdk/ssr/rendering-and-hydration.md +0 -103
  135. package/dist/docs/reference/sdk/ssr/serialize.md +0 -80
  136. package/dist/docs/reference/sdk/ssr/slots-and-placements.md +0 -113
  137. package/dist/docs/reference/sdk/steps.md +0 -86
  138. package/dist/docs/reference/sdk/type-generation.md +0 -265
  139. package/dist/docs/reference/tools/chrome-extension.md +0 -16
  140. package/dist/docs/reference/tools/cli.md +0 -292
  141. package/dist/docs/reference/tools/image-optimisation-service.md +0 -104
  142. package/dist/docs/reference/tools/mcp.md +0 -136
  143. package/dist/docs/reference/tools/vite-plugin.md +0 -163
  144. package/dist/docs/tutorials/first-api-call.md +0 -235
  145. package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +0 -143
  146. package/dist/docs/tutorials/first-experience.mdx +0 -254
  147. package/dist/docs/tutorials/first-server-rendered-page.mdx +0 -186
@@ -1,87 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Authentication
7
-
8
- The Picked API supports four ways to authenticate. They are a session from an email
9
- address and a password, an OAuth provider, a magic link, and an API key. This guide
10
- covers each one. It also covers how to control a session and how to use multi-factor
11
- authentication (MFA).
12
-
13
- ## Use a session
14
-
15
- After the caller has a session, it puts the access token in the `Authorization`
16
- header of every request that needs authentication:
17
-
18
- ```
19
- Authorization: Bearer <accessToken>
20
- ```
21
-
22
- The `expiresAt` field of the session gives the time at which the access token
23
- expires. The caller must refresh the session before that time.
24
-
25
- ### Authenticator assurance levels
26
-
27
- The session holds an `aal` field, and it gives the strength of the authentication:
28
-
29
- | Level | Meaning |
30
- |-------|---------|
31
- | `AAL1` | One factor: an email address and a password, OAuth, or a magic link |
32
- | `AAL2` | Two factors: the user verified a code from an authenticator app |
33
-
34
- Picked staff, and every member of an organization that requires MFA, must use `AAL2`.
35
- For these users, an `AAL1` session can only do these operations:
36
-
37
- - Read `user`.
38
- - Call the MFA mutations.
39
- - Call `passwordUpdate`, if the user has no verified authenticator. Therefore, a user can
40
- set a password before they add an authenticator.
41
-
42
- Every other operation returns the error code `MFA_REQUIRED`. Read `session.user.mfa` after
43
- `sessionCreate` to find out whether the user must verify, and see
44
- [How to set up MFA](/how-to/set-up-mfa) for the steps.
45
-
46
- The API checks the level when it creates a token. An OAuth token for an MCP client or the
47
- CLI is created at consent, which needs `AAL2` for these users. The token stays valid
48
- until it is revoked.
49
-
50
- ## The mutations
51
-
52
- | Mutation | What it does |
53
- | --- | --- |
54
- | `sessionStart` | Starts a sign-in from an email address alone. Returns `PASSWORD` when the account has a password, and `sessionCreate` completes the sign-in. Otherwise sends an email with a six-digit code and a sign-in link, and returns `EMAIL_CODE`, and `magicLinkVerify` completes the sign-in. An address with no account also gets `EMAIL_CODE`, but no email. Too many requests from one client return `RATE_LIMITED`. |
55
- | `sessionCreate` | Authenticates an email address and a password. Returns a session at `AAL1`. `session.user.mfa` says whether the user must verify. |
56
- | `sessionRefresh` | Exchanges a refresh token for a new session. Needs no `Authorization` header. |
57
- | `accountCreate` | Creates an account. `metadata` takes any JSON. |
58
- | `accountVerifyEmail` | Completes email verification with the token from the email. |
59
- | `accountResendVerification` | Sends the verification email again. |
60
- | `oauthAuthorize` | Returns the authorization URL for a provider. Google is supported. |
61
- | `oauthCallback` | Exchanges an OAuth code for a session. |
62
- | `magicLinkSend` | Sends an email with a six-digit code and a sign-in link to an account. Does not create an account. Returns `success: true` also for an address with no account, and sends no email to it. |
63
- | `magicLinkVerify` | Exchanges the six-digit code from the email for a session. |
64
- | `passwordResetSend` | Sends a password reset email. |
65
- | `passwordUpdate` | Sets or changes the password. Needs authentication. Needs `AAL2` when the user has a verified authenticator, also when the user does not have to use MFA. |
66
- | `mfaFactorEnroll` | Adds an authenticator app. A new factor is `UNVERIFIED`. Returns the QR code and the key one time. |
67
- | `mfaChallengeCreate` | Opens a challenge against a factor. |
68
- | `mfaChallengeVerify` | Verifies the code from the authenticator app. Moves the session to `AAL2`. |
69
- | `mfaFactorUnenroll` | Removes an authenticator. Needs `AAL2` for a verified factor. |
70
- | `apiKeyCreate` | Creates an API key. Only a user with a session can call it. |
71
- | `apiKeyRevoke` | Invalidates a key immediately. |
72
-
73
- ## Credentials
74
-
75
- | Credential | Header |
76
- | --- | --- |
77
- | Session access token | `Authorization: Bearer <accessToken>` |
78
- | API key | `x-api-key: pk_live_abc123...` |
79
-
80
- ## Related
81
-
82
- - [How to authenticate with a password](/how-to/authenticate-with-a-password)
83
- - [How to authenticate with OAuth](/how-to/authenticate-with-oauth)
84
- - [How to authenticate with a magic link](/how-to/authenticate-with-a-magic-link)
85
- - [How to set up MFA](/how-to/set-up-mfa)
86
- - [How to authenticate with an API key](/how-to/authenticate-with-an-api-key)
87
- - [Authorization and scopes](/reference/management-api/authorization-and-scopes)
@@ -1,291 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Authorization and scopes
7
-
8
- The Picked API controls access with scopes. Every authenticated caller carries a set
9
- of scopes, and those scopes decide which operations the caller can do. A caller is
10
- either a user with a session or an API key. This guide covers the scopes, the roles,
11
- and how the API resolves a permission.
12
-
13
- ## The format of a scope name
14
-
15
- A scope has the form `resource/action`:
16
-
17
- ```
18
- organization/read
19
- organization_members/create
20
- organization_projects/delete
21
- ```
22
-
23
- - **resource** — a lowercase name. It uses an underscore between words, as in
24
- `organization_members` and `organization_api_keys`.
25
- - **action** — one of `create`, `read`, `update`, or `delete`.
26
-
27
- The GraphQL schema holds the scopes in the `Scope` enum. There they are uppercase
28
- with an underscore between words, as in `ORGANIZATION_READ` and
29
- `ORGANIZATION_MEMBERS_CREATE`. The two forms name the same scope.
30
-
31
- ## Full scope list
32
-
33
- These are the scopes:
34
-
35
- ### Organization
36
-
37
- | Scope | GraphQL Enum | Description |
38
- | --------------------- | --------------------- | -------------------------------------------------------------- |
39
- | `organization/create` | `ORGANIZATION_CREATE` | Create an organization |
40
- | `organization/read` | `ORGANIZATION_READ` | Read the detail of an organization |
41
- | `organization/update` | `ORGANIZATION_UPDATE` | Update the name, the slug, and the settings of an organization |
42
- | `organization/delete` | `ORGANIZATION_DELETE` | Delete an organization |
43
-
44
- ### Organization members
45
-
46
- | Scope | GraphQL Enum | Description |
47
- | ----------------------------- | ----------------------------- | --------------------------------------- |
48
- | `organization_members/create` | `ORGANIZATION_MEMBERS_CREATE` | Add a member to an organization |
49
- | `organization_members/read` | `ORGANIZATION_MEMBERS_READ` | Read the member list of an organization |
50
- | `organization_members/update` | `ORGANIZATION_MEMBERS_UPDATE` | Update the role of a member |
51
- | `organization_members/delete` | `ORGANIZATION_MEMBERS_DELETE` | Remove a member from an organization |
52
-
53
- ### Organization invitations
54
-
55
- | Scope | GraphQL Enum | Description |
56
- | --------------------------------- | --------------------------------- | --------------------------------------------- |
57
- | `organization_invitations/create` | `ORGANIZATION_INVITATIONS_CREATE` | Send an invitation to join an organization |
58
- | `organization_invitations/read` | `ORGANIZATION_INVITATIONS_READ` | Read the invitations that wait for an answer |
59
- | `organization_invitations/delete` | `ORGANIZATION_INVITATIONS_DELETE` | Revoke an invitation that waits for an answer |
60
-
61
- ### Organization projects
62
-
63
- | Scope | GraphQL Enum | Description |
64
- | ------------------------------ | ------------------------------ | -------------------------------- |
65
- | `organization_projects/create` | `ORGANIZATION_PROJECTS_CREATE` | Create a project |
66
- | `organization_projects/read` | `ORGANIZATION_PROJECTS_READ` | Read the detail of a project |
67
- | `organization_projects/update` | `ORGANIZATION_PROJECTS_UPDATE` | Update the settings of a project |
68
- | `organization_projects/delete` | `ORGANIZATION_PROJECTS_DELETE` | Delete a project |
69
-
70
- A scope on content inside a project also gives `organization_projects/read`. The
71
- workspace, integration, lead, action run, and report scopes all give it. They do
72
- not give `organization_projects/create`, `organization_projects/update`, or
73
- `organization_projects/delete`.
74
-
75
- ### Organization API keys
76
-
77
- | Scope | GraphQL Enum | Description |
78
- | ------------------------------ | ------------------------------ | -------------------------------------------------------------------- |
79
- | `organization_api_keys/create` | `ORGANIZATION_API_KEYS_CREATE` | Create an API key |
80
- | `organization_api_keys/read` | `ORGANIZATION_API_KEYS_READ` | Read the API keys. This gives the prefix only, and not the full key. |
81
- | `organization_api_keys/delete` | `ORGANIZATION_API_KEYS_DELETE` | Revoke an API key |
82
-
83
- ### Organization integrations
84
-
85
- | Scope | GraphQL Enum | Description |
86
- | ---------------------------------- | ---------------------------------- | ------------------------------------- |
87
- | `organization_integrations/create` | `ORGANIZATION_INTEGRATIONS_CREATE` | Set up an integration |
88
- | `organization_integrations/read` | `ORGANIZATION_INTEGRATIONS_READ` | Read the options of an integration |
89
- | `organization_integrations/update` | `ORGANIZATION_INTEGRATIONS_UPDATE` | Change the settings of an integration |
90
- | `organization_integrations/delete` | `ORGANIZATION_INTEGRATIONS_DELETE` | Remove an integration |
91
-
92
- ### Organization reports
93
-
94
- | Scope | GraphQL Enum | Description |
95
- | ----------------------------- | ----------------------------- | ------------------------------- |
96
- | `organization_reports/create` | `ORGANIZATION_REPORTS_CREATE` | Create a report |
97
- | `organization_reports/read` | `ORGANIZATION_REPORTS_READ` | Read a report |
98
- | `organization_reports/update` | `ORGANIZATION_REPORTS_UPDATE` | Update the settings of a report |
99
- | `organization_reports/delete` | `ORGANIZATION_REPORTS_DELETE` | Delete a report |
100
-
101
- ## Roles
102
-
103
- Each member of an organization holds one of two roles:
104
-
105
- ### Owner
106
-
107
- An owner has full control inside the organization. These are the default scopes of an
108
- owner:
109
-
110
- - All `organization/*` scopes (`read`, `update`, `delete`)
111
- - All `organization_members/*` scopes
112
- - All `organization_invitations/*` scopes
113
- - `organization_projects/read`, `organization_projects/update`, `organization_projects/delete`
114
- - All `organization_api_keys/*` scopes
115
- - All `organization_integrations/*` scopes
116
- - `organization_reports/read`
117
-
118
- ### Member
119
-
120
- A member can reach most things, but cannot delete the organization and cannot control
121
- another member. These are the default scopes of a member:
122
-
123
- - `organization/read`, `organization/update`
124
- - `organization_members/read`
125
- - `organization_invitations/read`
126
- - `organization_projects/read`, `organization_projects/update`, `organization_projects/delete`
127
- - All `organization_api_keys/*` scopes
128
- - All `organization_integrations/*` scopes
129
- - `organization_reports/read`
130
-
131
- These are the differences between an owner and a member:
132
-
133
- | Capability | Owner | Member |
134
- | --------------------------------- | ----- | ------ |
135
- | Delete the organization | Yes | No |
136
- | Invite new members | Yes | No |
137
- | Remove members | Yes | No |
138
- | Update member roles | Yes | No |
139
- | Revoke invitations | Yes | No |
140
- | Control projects and integrations | Yes | Yes |
141
- | Control API keys | Yes | Yes |
142
- | Read reports | Yes | Yes |
143
-
144
- ## How scopes are resolved
145
-
146
- When an authenticated request reaches the API, the API resolves the scopes like this:
147
-
148
- 1. **A user with a session** — the API finds the role of that caller in the target
149
- organization. It then gives the caller the default scopes of that role.
150
- 2. **A request with an API key** — the API uses the scopes that the key received when
151
- somebody created it. Those scopes are always scopes of the user who created the
152
- key.
153
-
154
- Most queries and mutations point at one organization. For those, the caller must hold
155
- the scope inside that organization. For a root-level operation such as
156
- `organizationCreate`, the API resolves the scope at the account level.
157
-
158
- When the caller does not hold the scope that an operation needs, the API returns an
159
- authorization error with the code `FORBIDDEN`. See [Errors](/reference/management-api/error-handling).
160
-
161
- ## Operations and required scopes
162
-
163
- This table gives the scope that each common operation needs:
164
-
165
- ### Queries
166
-
167
- | Query | Required Scope |
168
- | ------------------------- | -------------------------------- |
169
- | `organization` | `organization/read` |
170
- | `organizations` | `organization/read` |
171
- | `project` | `organization_projects/read` |
172
- | `apiKeys` | `organization_api_keys/read` |
173
- | `shopifyWebhooks` | `organization_integrations/read` |
174
- | `shopifyMetafieldConfigs` | `organization_integrations/read` |
175
- | `report` | `organization_reports/read` |
176
-
177
- ### Mutations
178
-
179
- | Mutation | Required Scope |
180
- | ------------------------------ | ---------------------------------- |
181
- | `organizationCreate` | `organization/create` |
182
- | `organizationUpdate` | `organization/update` |
183
- | `organizationDelete` | `organization/delete` |
184
- | `organizationMemberInvite` | `organization_invitations/create` |
185
- | `organizationInvitationRevoke` | `organization_invitations/delete` |
186
- | `organizationMemberRemove` | `organization_members/delete` |
187
- | `organizationMemberRoleUpdate` | `organization_members/update` |
188
- | `projectCreate` | `organization_projects/create` |
189
- | `apiKeyCreate` | `organization_api_keys/create` |
190
- | `apiKeyRevoke` | `organization_api_keys/delete` |
191
- | `shopifyWebhookCreate` | `organization_integrations/create` |
192
- | `shopifyWebhookUpdate` | `organization_integrations/update` |
193
- | `shopifyWebhookDelete` | `organization_integrations/delete` |
194
- | `shopifyMetafieldConfigCreate` | `organization_integrations/create` |
195
- | `shopifyMetafieldConfigUpdate` | `organization_integrations/update` |
196
- | `shopifyMetafieldConfigDelete` | `organization_integrations/delete` |
197
- | `reportCreate` | `organization_reports/create` |
198
- | `reportUpdate` | `organization_reports/update` |
199
- | `reportDelete` | `organization_reports/delete` |
200
-
201
- Some mutations do not require organization-level scopes because they operate on the caller's own data:
202
-
203
- | Mutation | Requirement |
204
- | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
205
- | `sessionStart` / `sessionCreate` / `sessionRefresh` | No authentication required |
206
- | `accountCreate` / `accountVerifyEmail` / `accountResendVerification` | No authentication required |
207
- | `oauthAuthorize` / `oauthCallback` | No authentication required |
208
- | `magicLinkSend` / `magicLinkVerify` | No authentication required |
209
- | `passwordResetSend` | No authentication required |
210
- | `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. |
211
- | `organizationInvitationAccept` / `organizationInvitationDecline` | Authenticated session (no specific scope) |
212
- | `mfaFactorEnroll` / `mfaChallengeCreate` / `mfaChallengeVerify` / `mfaFactorUnenroll` | Authenticated session (no specific scope). Exempt from the MFA requirement, so a user can add a factor and verify it. |
213
-
214
- `userMfaReset` needs the root-level scope `users/reset_mfa` (`USERS_RESET_MFA`). The
215
- mutation removes every authenticator of a user and signs the user out everywhere, so
216
- their next sign-in starts at the setup.
217
-
218
- ## Read your scopes
219
-
220
- ### Root-level scopes
221
-
222
- The `viewerScopes` query returns the root-level scopes for the authenticated caller:
223
-
224
- ```graphql
225
- query {
226
- viewerScopes
227
- }
228
- ```
229
-
230
- Response:
231
-
232
- ```json
233
- {
234
- "data": {
235
- "viewerScopes": ["ORGANIZATION_CREATE"]
236
- }
237
- }
238
- ```
239
-
240
- ### Organization-level scopes
241
-
242
- Each `Organization` object exposes a `viewerScopes` field that returns the scopes the caller has within that specific organization:
243
-
244
- ```graphql
245
- query {
246
- organization(input: { slug: "my-company" }) {
247
- id
248
- name
249
- viewerScopes
250
- }
251
- }
252
- ```
253
-
254
- Response:
255
-
256
- ```json
257
- {
258
- "data": {
259
- "organization": {
260
- "id": "org_abc123",
261
- "name": "My Company",
262
- "viewerScopes": [
263
- "ORGANIZATION_READ",
264
- "ORGANIZATION_UPDATE",
265
- "ORGANIZATION_MEMBERS_READ",
266
- "ORGANIZATION_PROJECTS_READ",
267
- "ORGANIZATION_PROJECTS_UPDATE",
268
- "ORGANIZATION_PROJECTS_DELETE",
269
- "ORGANIZATION_API_KEYS_CREATE",
270
- "ORGANIZATION_API_KEYS_READ",
271
- "ORGANIZATION_API_KEYS_DELETE",
272
- "ORGANIZATION_INTEGRATIONS_CREATE",
273
- "ORGANIZATION_INTEGRATIONS_READ",
274
- "ORGANIZATION_INTEGRATIONS_UPDATE",
275
- "ORGANIZATION_INTEGRATIONS_DELETE",
276
- "ORGANIZATION_REPORTS_READ"
277
- ]
278
- }
279
- }
280
- }
281
- ```
282
-
283
- Use this to build a UI that changes with the permissions of the caller. An example is
284
- a **Delete Organization** button that the UI hides when the caller does not hold
285
- `ORGANIZATION_DELETE`.
286
-
287
- ## Related
288
-
289
- - [Authentication](/reference/management-api/authentication)
290
- - [How to authenticate with an API key](/how-to/authenticate-with-an-api-key)
291
- - [API keys](/reference/dashboard/api-keys) — the dashboard surface.
@@ -1,232 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Errors
7
-
8
- The Picked API returns an error in the standard GraphQL format. This guide covers the
9
- shape of an error response, every error code, and what your code must do with each
10
- one.
11
-
12
- ## Error response shape
13
-
14
- When an operation fails, the API returns an `errors` array in the response body. Each
15
- error object holds these fields:
16
-
17
- ```json
18
- {
19
- "data": null,
20
- "errors": [
21
- {
22
- "message": "A human-readable description of the error",
23
- "path": ["mutationName"],
24
- "extensions": {
25
- "code": "ERROR_CODE"
26
- }
27
- }
28
- ]
29
- }
30
- ```
31
-
32
- | Field | Description |
33
- |-------|-------------|
34
- | `message` | A description of the error that a person can read. Put it in your log. Do not write code against it. |
35
- | `path` | The path to the field in the query that made the error. |
36
- | `extensions.code` | An error code that a machine can read. Write your code against this field. |
37
-
38
- One response can hold more than one error. The `data` field is `null` when the whole
39
- operation failed. It holds part of the data when only some fields failed.
40
-
41
- ## Authentication error codes
42
-
43
- These errors come from a session, an account, OAuth, a magic link, a password
44
- operation, or MFA. They match the `AuthErrorCode` enum in the schema.
45
-
46
- | Code | Description |
47
- |------|-------------|
48
- | `INVALID_CREDENTIALS` | The email address and the password do not match. |
49
- | `EMAIL_NOT_CONFIRMED` | The account is there, but nobody verified the email address. See [Authentication](/reference/management-api/authentication#the-mutations). |
50
- | `USER_NOT_FOUND` | There is no account with that email address. |
51
- | `USER_ALREADY_EXISTS` | An account with that email address is there already. The API returns this when you create an account. |
52
- | `WEAK_PASSWORD` | The password is not strong enough. |
53
- | `INVALID_TOKEN` | The token is invalid or malformed. This covers a verification token, a reset token, and a magic link token. |
54
- | `TOKEN_EXPIRED` | The token expired. Ask for a new one. |
55
- | `MFA_CHALLENGE_FAILED` | The MFA verification code is not correct. |
56
- | `MFA_FACTOR_NOT_FOUND` | That MFA factor is not there, or it belongs to another caller. |
57
- | `MFA_REQUIRED` | The user must verify a code from an authenticator app before this operation. Complete the challenge, then use the returned session. |
58
- | `OAUTH_PROVIDER_ERROR` | The exchange with the OAuth provider, such as Google, failed. |
59
- | `RATE_LIMITED` | Too many requests in a short period. Wait, then try again. |
60
-
61
- ### Example: invalid credentials
62
-
63
- ```json
64
- {
65
- "data": {
66
- "sessionCreate": {
67
- "session": null
68
- }
69
- },
70
- "errors": [
71
- {
72
- "message": "Invalid credentials",
73
- "path": ["sessionCreate"],
74
- "extensions": {
75
- "code": "INVALID_CREDENTIALS"
76
- }
77
- }
78
- ]
79
- }
80
- ```
81
-
82
- ## Authorization error codes
83
-
84
- An authorization error happens when the caller does not hold the
85
- [scope](/reference/management-api/authorization-and-scopes) that an operation needs.
86
-
87
- | Code | Description |
88
- |------|-------------|
89
- | `UNAUTHORIZED` | The request carries no valid authentication. It has no `Authorization` header and no `x-api-key` header, or the token is invalid. |
90
- | `FORBIDDEN` | The caller is authenticated, but it does not hold the scope that the operation needs. |
91
-
92
- ### Example: the scope is not enough
93
-
94
- A caller that holds `organization/read` only tries to delete an organization. It
95
- receives this:
96
-
97
- ```json
98
- {
99
- "data": {
100
- "organizationDelete": null
101
- },
102
- "errors": [
103
- {
104
- "message": "Insufficient permissions",
105
- "path": ["organizationDelete"],
106
- "extensions": {
107
- "code": "FORBIDDEN"
108
- }
109
- }
110
- ]
111
- }
112
- ```
113
-
114
- ## Organization, member, and invitation error codes
115
-
116
- These errors come from an organization, a member operation, or an invitation. They
117
- match the `ErrorCode` enum in the schema.
118
-
119
- ### Organization errors
120
-
121
- | Code | Description |
122
- |------|-------------|
123
- | `ORGANIZATION_NOT_FOUND` | That organization is not there, or the caller cannot reach it. |
124
- | `ORGANIZATION_ALREADY_EXISTS` | An organization with that name is there already. |
125
- | `SLUG_ALREADY_EXISTS` | Another organization uses that slug already. |
126
- | `INVALID_SLUG` | The slug holds an invalid character. A slug takes lowercase letters, digits, and hyphens only. |
127
-
128
- ### Member errors
129
-
130
- | Code | Description |
131
- |------|-------------|
132
- | `MEMBER_NOT_FOUND` | That user is not a member of the organization. |
133
- | `MEMBER_ALREADY_EXISTS` | The user is a member of the organization already. |
134
- | `CANNOT_REMOVE_PRIMARY_OWNER` | You cannot remove the primary owner of an organization. |
135
- | `CANNOT_CHANGE_OWN_ROLE` | A member cannot change the role of that same member. Another owner must do it. |
136
-
137
- ### Invitation errors
138
-
139
- | Code | Description |
140
- |------|-------------|
141
- | `INVITATION_NOT_FOUND` | That invitation is not there. |
142
- | `INVITATION_EXPIRED` | The invitation expired. Nobody can accept it now. |
143
- | `INVITATION_ALREADY_ACCEPTED` | Somebody accepted the invitation already. |
144
-
145
- ### Project errors
146
-
147
- | Code | Description |
148
- |------|-------------|
149
- | `PROJECT_NOT_FOUND` | That project is not there, or the caller cannot reach it. |
150
-
151
- ### General errors
152
-
153
- | Code | Description |
154
- |------|-------------|
155
- | `VALIDATION_ERROR` | The input failed a validation rule. Read the `message` field to learn which field is invalid. |
156
- | `INTERNAL_ERROR` | The server met an unexpected error. Try the request again. Contact support when the error continues. |
157
-
158
- ## What your code must do
159
-
160
- ### Look for an error first
161
-
162
- Check every response for an `errors` array before you read `data`:
163
-
164
- ```javascript
165
- const response = await fetch('/graphql', {
166
- method: 'POST',
167
- headers: {
168
- 'Content-Type': 'application/json',
169
- 'Authorization': `Bearer ${accessToken}`,
170
- },
171
- body: JSON.stringify({ query, variables }),
172
- });
173
-
174
- const result = await response.json();
175
-
176
- if (result.errors) {
177
- for (const error of result.errors) {
178
- const code = error.extensions?.code;
179
-
180
- switch (code) {
181
- case 'UNAUTHORIZED':
182
- // Send the user to the sign-in page.
183
- break;
184
- case 'FORBIDDEN':
185
- // Show a permissions error.
186
- break;
187
- case 'RATE_LIMITED':
188
- // Wait, then try again.
189
- break;
190
- default:
191
- // Put the message in the log, or show it.
192
- console.error(error.message);
193
- }
194
- }
195
- }
196
- ```
197
-
198
- ### Refresh a token that expired
199
-
200
- A request can return `UNAUTHORIZED` while the caller holds a refresh token. Try a
201
- [session refresh](/reference/management-api/authentication#the-mutations) first. Do not treat it as a
202
- failure to sign in:
203
-
204
- ```javascript
205
- if (code === 'UNAUTHORIZED' && refreshToken) {
206
- const refreshResult = await sessionRefresh(refreshToken);
207
- if (refreshResult.session) {
208
- // Try the first request again with the new access token.
209
- } else {
210
- // Send the user to the sign-in page.
211
- }
212
- }
213
- ```
214
-
215
- ### Read data that is only part complete
216
-
217
- GraphQL can return part of the data together with an error. Take a query that reads
218
- an organization and its members. It can succeed for the organization and fail for the
219
- members, when the caller does not hold `organization_members/read`. The response then
220
- holds `data` with the organization, and `errors` for the members field. Always read
221
- both.
222
-
223
- ### Try again after a transient failure
224
-
225
- `INTERNAL_ERROR` and `RATE_LIMITED` are both transient. For `RATE_LIMITED`, use an
226
- exponential backoff before you try again. For `INTERNAL_ERROR`, one more try is
227
- usually enough.
228
-
229
- ## Related
230
-
231
- - [Authentication](/reference/management-api/authentication)
232
- - [Your first API call](/tutorials/first-api-call)