@picked/client 0.0.70-next.6 → 0.0.71-next.1

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 (177) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/api-CH2FNa6S.cjs +1 -0
  3. package/dist/api-CgqRvuKL.js +38 -0
  4. package/dist/cjs/form/index.js +1 -1
  5. package/dist/cjs/index.js +2 -2
  6. package/dist/cjs/plugins/dom-observer/index.js +1 -1
  7. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  8. package/dist/cjs/server/index.js +1 -1
  9. package/dist/docs/actions.mdx +38 -18
  10. package/dist/docs/api/authentication.md +75 -48
  11. package/dist/docs/api/authorization-and-scopes.md +63 -47
  12. package/dist/docs/api/error-handling.md +70 -54
  13. package/dist/docs/api/index.md +41 -22
  14. package/dist/docs/api/pagination.md +30 -20
  15. package/dist/docs/api-keys.mdx +11 -6
  16. package/dist/docs/chrome-extension.md +22 -5
  17. package/dist/docs/conditions.mdx +32 -19
  18. package/dist/docs/content/asset-library.mdx +65 -34
  19. package/dist/docs/content/content-entries.mdx +8 -2
  20. package/dist/docs/content/layouts.mdx +45 -29
  21. package/dist/docs/content/pages.mdx +29 -14
  22. package/dist/docs/content/sections.mdx +19 -8
  23. package/dist/docs/delivery-api/experience-content.md +10 -5
  24. package/dist/docs/delivery-api/index.md +19 -12
  25. package/dist/docs/delivery-api/preview-caching-crawling.md +27 -14
  26. package/dist/docs/delivery-api/project-config.md +6 -4
  27. package/dist/docs/experiences.mdx +26 -10
  28. package/dist/docs/features.mdx +66 -25
  29. package/dist/docs/fields.mdx +42 -27
  30. package/dist/docs/flow-builder/building-flows.md +38 -20
  31. package/dist/docs/flow-builder/condition-builder.md +32 -21
  32. package/dist/docs/flow-builder/keyboard-shortcuts.md +18 -18
  33. package/dist/docs/flow-builder/nodes.md +26 -13
  34. package/dist/docs/flow-builder/overview.mdx +28 -15
  35. package/dist/docs/gtm-template.md +35 -26
  36. package/dist/docs/guides/build-a-personalized-page.mdx +36 -18
  37. package/dist/docs/image-optimisation-service.md +33 -17
  38. package/dist/docs/index.md +28 -17
  39. package/dist/docs/mcp.md +46 -38
  40. package/dist/docs/pickedql/data-sources.md +65 -43
  41. package/dist/docs/pickedql/dimensions.md +27 -12
  42. package/dist/docs/pickedql/examples.md +38 -26
  43. package/dist/docs/pickedql/filtering.md +10 -6
  44. package/dist/docs/pickedql/index.md +32 -14
  45. package/dist/docs/pickedql/schema.md +85 -76
  46. package/dist/docs/pickedql/virtual-functions.md +62 -36
  47. package/dist/docs/projects.mdx +14 -7
  48. package/dist/docs/reports.mdx +5 -3
  49. package/dist/docs/sdk/actions.md +33 -17
  50. package/dist/docs/sdk/conditions.md +8 -5
  51. package/dist/docs/sdk/content-security-policy.md +5 -4
  52. package/dist/docs/sdk/experiences.md +29 -11
  53. package/dist/docs/sdk/feature-allocation.md +79 -47
  54. package/dist/docs/sdk/features.md +130 -76
  55. package/dist/docs/sdk/fields.md +66 -42
  56. package/dist/docs/sdk/index.md +22 -13
  57. package/dist/docs/sdk/plugins/create-experience.md +18 -15
  58. package/dist/docs/sdk/plugins/dynamic-experiences.md +42 -16
  59. package/dist/docs/sdk/predicates.md +53 -37
  60. package/dist/docs/sdk/ssr/index.md +25 -8
  61. package/dist/docs/sdk/ssr/rendering-and-hydration.md +37 -16
  62. package/dist/docs/sdk/ssr/serialize.md +38 -20
  63. package/dist/docs/sdk/ssr/slots-and-placements.md +28 -10
  64. package/dist/docs/sdk/steps.md +100 -55
  65. package/dist/docs/steps.mdx +20 -11
  66. package/dist/docs/team-management.md +17 -11
  67. package/dist/docs/vite-plugin.md +26 -19
  68. package/dist/docs/workspace-versioning.mdx +14 -8
  69. package/dist/docs/workspaces.mdx +55 -24
  70. package/dist/{dom-BwmTHeT7.js → dom-BqcToNL0.js} +1 -3
  71. package/dist/{dom-CDrHc_j9.cjs → dom-DlLH3FxV.cjs} +1 -1
  72. package/dist/esm/form/index.js +2 -4
  73. package/dist/esm/index.js +50 -45
  74. package/dist/esm/plugins/dom-observer/index.js +1 -1
  75. package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
  76. package/dist/esm/preview/index.js +1 -1
  77. package/dist/esm/server/index.js +12 -10
  78. package/dist/{experience-instance-DOJShRk5.js → experience-instance-DGk11d8a.js} +3 -3
  79. package/dist/experience-instance-Dej3P1sE.cjs +1 -0
  80. package/dist/{plugin-BxMR7fOV.js → plugin-D2UqFikQ.js} +2 -2
  81. package/dist/plugin-DCW-tnjO.cjs +1 -0
  82. package/dist/{preview-channel-DW9J8t4B.js → preview-channel-CSr96XAo.js} +1 -1
  83. package/dist/{protocol-DSqOlW2r.js → protocol-C5KkkiZc.js} +1 -1
  84. package/dist/types/client.d.ts +7 -6
  85. package/dist/types/entities/action/action.d.ts +5 -4
  86. package/dist/types/entities/action/action.d.ts.map +1 -1
  87. package/dist/types/entities/component/component.d.ts +6 -5
  88. package/dist/types/entities/component/component.d.ts.map +1 -1
  89. package/dist/types/entities/condition/condition.d.ts +5 -5
  90. package/dist/types/entities/content/content.d.ts +4 -3
  91. package/dist/types/entities/experience/experience.d.ts +11 -10
  92. package/dist/types/entities/experience/experience.d.ts.map +1 -1
  93. package/dist/types/entities/experience-instance/experience-instance.d.ts +10 -9
  94. package/dist/types/entities/feature/feature.d.ts +3 -2
  95. package/dist/types/entities/feature/feature.d.ts.map +1 -1
  96. package/dist/types/entities/field/field.d.ts +7 -6
  97. package/dist/types/entities/framework/framework.d.ts +7 -6
  98. package/dist/types/entities/framework/framework.d.ts.map +1 -1
  99. package/dist/types/entities/history/history.d.ts +6 -6
  100. package/dist/types/entities/plugin/plugin.d.ts +3 -2
  101. package/dist/types/entities/plugin/plugin.d.ts.map +1 -1
  102. package/dist/types/entities/predicate/predicate.d.ts +4 -3
  103. package/dist/types/entities/predicate/predicate.d.ts.map +1 -1
  104. package/dist/types/entities/response/response-validation.d.ts +3 -2
  105. package/dist/types/entities/response/response.d.ts +12 -11
  106. package/dist/types/entities/session/session.d.ts +2 -1
  107. package/dist/types/entities/step/step.d.ts +6 -5
  108. package/dist/types/exports.d.ts +2 -1
  109. package/dist/types/exports.d.ts.map +1 -1
  110. package/dist/types/form/build-responses.d.ts +2 -1
  111. package/dist/types/form/create-field-evaluator.d.ts +4 -3
  112. package/dist/types/form/create-field-validation.d.ts +5 -4
  113. package/dist/types/form/create-form.d.ts +7 -6
  114. package/dist/types/form/create-submit-pipeline.d.ts +7 -6
  115. package/dist/types/form/get-step-fields.d.ts +3 -2
  116. package/dist/types/lifecycle/condition-selection.d.ts +14 -4
  117. package/dist/types/lifecycle/lifecycle.d.ts +4 -3
  118. package/dist/types/lifecycle/rules-logic.d.ts +4 -3
  119. package/dist/types/lifecycle/state-snapshot.d.ts +4 -3
  120. package/dist/types/picked.d.ts +64 -62
  121. package/dist/types/picked.d.ts.map +1 -1
  122. package/dist/types/ping.d.ts +1 -1
  123. package/dist/types/ping.d.ts.map +1 -1
  124. package/dist/types/plugins/create-experience/create-experience.d.ts +9 -8
  125. package/dist/types/plugins/create-experience/create-experience.d.ts.map +1 -1
  126. package/dist/types/plugins/create-experience/plugin.d.ts +3 -2
  127. package/dist/types/plugins/create-experience/plugin.d.ts.map +1 -1
  128. package/dist/types/plugins/create-experience/serialization.d.ts.map +1 -1
  129. package/dist/types/plugins/dom-observer/plugin.d.ts +1 -1
  130. package/dist/types/plugins/dynamic-experiences/plugin.d.ts +3 -3
  131. package/dist/types/plugins/dynamic-experiences/types.d.ts +8 -5
  132. package/dist/types/plugins/experience-browser-storage/plugin.d.ts +1 -1
  133. package/dist/types/plugins/experience-browser-storage/plugin.d.ts.map +1 -1
  134. package/dist/types/plugins/history-browser-storage/plugin.d.ts +1 -1
  135. package/dist/types/plugins/history-browser-storage/plugin.d.ts.map +1 -1
  136. package/dist/types/plugins/responses-browser-storage/plugin.d.ts +1 -1
  137. package/dist/types/plugins/responses-browser-storage/plugin.d.ts.map +1 -1
  138. package/dist/types/plugins/responses-indexeddb/plugin.d.ts +1 -1
  139. package/dist/types/plugins/single-page-app/plugin.d.ts +1 -1
  140. package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
  141. package/dist/types/plugins/web-components/plugin.d.ts +2 -1
  142. package/dist/types/plugins/window-object/plugin.d.ts +2 -2
  143. package/dist/types/preview-channel.d.ts +5 -1
  144. package/dist/types/preview-receiver/index.d.ts +18 -1
  145. package/dist/types/preview-receiver/protocol.d.ts +10 -1
  146. package/dist/types/server/index.d.ts +3 -3
  147. package/dist/types/server/serialize.d.ts +2 -2
  148. package/dist/types/utils/dom.d.ts +2 -1
  149. package/dist/types/utils/events.d.ts +6 -6
  150. package/dist/types/utils/events.d.ts.map +1 -1
  151. package/dist/types/utils/global-obj.d.ts +1 -1
  152. package/dist/types/utils/global-obj.d.ts.map +1 -1
  153. package/dist/types/utils/id.d.ts.map +1 -1
  154. package/dist/types/utils/logger.d.ts +2 -1
  155. package/dist/types/utils/logger.d.ts.map +1 -1
  156. package/dist/types/utils/node-tree/get-next-node-from-action.d.ts +2 -1
  157. package/dist/types/utils/node-tree/get-next-node-from-condition.d.ts +2 -1
  158. package/dist/types/utils/node-tree/get-next-node.d.ts +1 -1
  159. package/dist/types/utils/node-tree/get-next-node.d.ts.map +1 -1
  160. package/dist/types/utils/node-tree/get-origin-node.d.ts +1 -1
  161. package/dist/types/utils/node-tree/get-origin-node.d.ts.map +1 -1
  162. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts +1 -1
  163. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts.map +1 -1
  164. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts +1 -1
  165. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts.map +1 -1
  166. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts +1 -1
  167. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts.map +1 -1
  168. package/dist/types/utils/nodes.d.ts +1 -1
  169. package/dist/types/utils/picked-config.d.ts +2 -1
  170. package/dist/types/utils/rules-logic.d.ts +6 -2
  171. package/dist/types/utils/storage.d.ts +1 -1
  172. package/dist/types/utils/storage.d.ts.map +1 -1
  173. package/package.json +22 -23
  174. package/dist/api-CoUkIxIr.cjs +0 -1
  175. package/dist/api-ahdSBQ3Y.js +0 -40
  176. package/dist/experience-instance-DurC3pE-.cjs +0 -1
  177. package/dist/plugin-CASdGtTX.cjs +0 -1
@@ -4,11 +4,15 @@ layout: docs
4
4
 
5
5
  # Authentication
6
6
 
7
- The Picked API supports multiple authentication methods: email/password sessions, OAuth providers, magic links, and API keys. This guide covers each method and explains how to manage sessions and multi-factor authentication (MFA).
7
+ The Picked API supports four ways to authenticate. They are a session from an email
8
+ address and a password, an OAuth provider, a magic link, and an API key. This guide
9
+ covers each one. It also covers how to control a session and how to use multi-factor
10
+ authentication (MFA).
8
11
 
9
- ## Email and password login
12
+ ## Sign in with an email address and a password
10
13
 
11
- The `sessionCreate` mutation authenticates a user with email and password and returns a session.
14
+ The `sessionCreate` mutation authenticates a user from an email address and a
15
+ password. It returns a session.
12
16
 
13
17
  ```graphql
14
18
  mutation {
@@ -36,13 +40,16 @@ mutation {
36
40
  }
37
41
  ```
38
42
 
39
- If the user has MFA enabled, the response sets `requiresMfa` to `true` and returns the enrolled `mfaFactors`. The caller must complete an MFA challenge before receiving a fully authenticated session. See the [MFA](#multi-factor-authentication-mfa) section below.
43
+ When the user has MFA on, the response sets `requiresMfa` to `true` and returns the
44
+ `mfaFactors` of that user. The caller must then complete an MFA challenge before it
45
+ receives a full session. See [MFA](#multi-factor-authentication-mfa) below.
40
46
 
41
- If MFA is not enabled, the response includes a `session` with an `accessToken`, a `refreshToken`, and an `expiresAt` timestamp.
47
+ When MFA is off, the response holds a `session` with an `accessToken`, a
48
+ `refreshToken`, and an `expiresAt` timestamp.
42
49
 
43
- ## Account creation
50
+ ## Create an account
44
51
 
45
- New accounts are created with the `accountCreate` mutation:
52
+ The `accountCreate` mutation creates a new account:
46
53
 
47
54
  ```graphql
48
55
  mutation {
@@ -63,11 +70,14 @@ mutation {
63
70
  }
64
71
  ```
65
72
 
66
- The `metadata` field is optional and accepts arbitrary JSON for storing profile information. When email verification is required, the returned session is `null` until the email is verified.
73
+ The `metadata` field is optional. It takes any JSON, and you can hold profile
74
+ information in it. When the account needs email verification, the session in the
75
+ response is `null` until the user verifies the email address.
67
76
 
68
- ## Email verification
77
+ ## Verify an email address
69
78
 
70
- After account creation, the user receives a verification email containing a token. The `accountVerifyEmail` mutation completes verification:
79
+ After you create the account, the user receives a verification email with a token.
80
+ The `accountVerifyEmail` mutation completes the verification:
71
81
 
72
82
  ```graphql
73
83
  mutation {
@@ -83,7 +93,7 @@ mutation {
83
93
  }
84
94
  ```
85
95
 
86
- If the verification email needs to be resent:
96
+ To send the verification email again:
87
97
 
88
98
  ```graphql
89
99
  mutation {
@@ -95,11 +105,11 @@ mutation {
95
105
  }
96
106
  ```
97
107
 
98
- ## OAuth flow (Google)
108
+ ## The OAuth flow with Google
99
109
 
100
110
  The API supports Google as an OAuth provider. The flow has two steps.
101
111
 
102
- ### Step 1: Get the authorization URL
112
+ ### Step 1: get the authorization URL
103
113
 
104
114
  ```graphql
105
115
  mutation {
@@ -113,9 +123,11 @@ mutation {
113
123
  }
114
124
  ```
115
125
 
116
- The caller redirects the user to the returned `url`. After the user authenticates with Google, they are redirected back to a URL on the same dashboard deployment with a `code` parameter, where the caller exchanges it for a session.
126
+ The caller sends the user to the `url` in the response. The user authenticates with
127
+ Google. Google then sends the user back to a URL on the same dashboard deployment,
128
+ with a `code` parameter. The caller exchanges that code for a session.
117
129
 
118
- ### Step 2: Exchange the code for a session
130
+ ### Step 2: exchange the code for a session
119
131
 
120
132
  ```graphql
121
133
  mutation {
@@ -134,7 +146,7 @@ mutation {
134
146
 
135
147
  ## Magic links
136
148
 
137
- Magic links allow passwordless authentication via email.
149
+ A magic link authenticates a user through an email address, with no password.
138
150
 
139
151
  ### Send a magic link
140
152
 
@@ -149,7 +161,7 @@ mutation {
149
161
  }
150
162
  ```
151
163
 
152
- The user receives an email containing a link with a token.
164
+ The user receives an email with a link, and the link holds a token.
153
165
 
154
166
  ### Verify the magic link
155
167
 
@@ -167,11 +179,11 @@ mutation {
167
179
  }
168
180
  ```
169
181
 
170
- ## Password management
182
+ ## Passwords
171
183
 
172
- ### Reset a forgotten password
184
+ ### Reset a password
173
185
 
174
- Send a password reset email:
186
+ Send an email to reset the password:
175
187
 
176
188
  ```graphql
177
189
  mutation {
@@ -184,7 +196,7 @@ mutation {
184
196
  }
185
197
  ```
186
198
 
187
- Complete the reset with the token from the email:
199
+ Complete the reset with the token from that email:
188
200
 
189
201
  ```graphql
190
202
  mutation {
@@ -201,9 +213,9 @@ mutation {
201
213
  }
202
214
  ```
203
215
 
204
- ### Update an existing password
216
+ ### Change a password
205
217
 
206
- This mutation requires authentication:
218
+ This mutation needs authentication:
207
219
 
208
220
  ```graphql
209
221
  mutation {
@@ -218,9 +230,11 @@ mutation {
218
230
 
219
231
  ## Multi-factor authentication (MFA)
220
232
 
221
- MFA adds a second layer of security using phone-based verification. The API supports enrolling, challenging, verifying, and unenrolling MFA factors. All MFA mutations require authentication.
233
+ MFA adds a second layer of security, and it uses a telephone to verify the user. The
234
+ API can add an MFA factor, send a challenge, verify a challenge, and remove a factor.
235
+ Every MFA mutation needs authentication.
222
236
 
223
- ### Enroll a factor
237
+ ### Add a factor
224
238
 
225
239
  ```graphql
226
240
  mutation {
@@ -238,7 +252,7 @@ mutation {
238
252
  }
239
253
  ```
240
254
 
241
- A newly enrolled factor has a status of `UNVERIFIED` until confirmed via a challenge.
255
+ A new factor has the status `UNVERIFIED` until a challenge confirms it.
242
256
 
243
257
  ### Send a challenge
244
258
 
@@ -252,7 +266,7 @@ mutation {
252
266
  }
253
267
  ```
254
268
 
255
- This sends a verification code to the enrolled phone number.
269
+ This sends a verification code to the telephone number of the factor.
256
270
 
257
271
  ### Verify the challenge
258
272
 
@@ -272,9 +286,10 @@ mutation {
272
286
  }
273
287
  ```
274
288
 
275
- On success, the session is upgraded to Authenticator Assurance Level `AAL2`. The factor status changes to `VERIFIED`.
289
+ On success, the session moves to Authenticator Assurance Level `AAL2`. The status of
290
+ the factor changes to `VERIFIED`.
276
291
 
277
- ### Unenroll a factor
292
+ ### Remove a factor
278
293
 
279
294
  ```graphql
280
295
  mutation {
@@ -286,30 +301,34 @@ mutation {
286
301
  }
287
302
  ```
288
303
 
289
- ## Using a session
304
+ ## Use a session
290
305
 
291
- After obtaining a session, the caller includes the access token in the `Authorization` header of every authenticated request:
306
+ After the caller has a session, it puts the access token in the `Authorization`
307
+ header of every request that needs authentication:
292
308
 
293
309
  ```
294
310
  Authorization: Bearer <accessToken>
295
311
  ```
296
312
 
297
- The `expiresAt` field on the session indicates when the access token expires. The caller should refresh the session before the token expires.
313
+ The `expiresAt` field of the session gives the time at which the access token
314
+ expires. The caller must refresh the session before that time.
298
315
 
299
316
  ### Authenticator assurance levels
300
317
 
301
- The session includes an `aal` field indicating the authentication strength:
318
+ The session holds an `aal` field, and it gives the strength of the authentication:
302
319
 
303
320
  | Level | Meaning |
304
321
  |-------|---------|
305
- | `AAL1` | Single-factor authentication (email/password, OAuth, or magic link) |
306
- | `AAL2` | Multi-factor authentication (MFA challenge completed) |
322
+ | `AAL1` | One factor: an email address and a password, OAuth, or a magic link |
323
+ | `AAL2` | More than one factor: the user completed an MFA challenge |
307
324
 
308
- Some operations may require `AAL2`. If a caller with `AAL1` attempts such an operation, the API returns an authorization error.
325
+ Some operations need `AAL2`. When a caller at `AAL1` tries one of them, the API
326
+ returns an authorization error.
309
327
 
310
- ## Session refresh
328
+ ## Refresh a session
311
329
 
312
- Access tokens are short-lived. The `sessionRefresh` mutation exchanges a refresh token for a new session:
330
+ An access token has a short life. The `sessionRefresh` mutation exchanges a refresh
331
+ token for a new session:
313
332
 
314
333
  ```graphql
315
334
  mutation {
@@ -325,11 +344,14 @@ mutation {
325
344
  }
326
345
  ```
327
346
 
328
- The response includes a new `accessToken` and a new `refreshToken`. The previous refresh token is invalidated. This mutation does not require the `Authorization` header.
347
+ The response holds a new `accessToken` and a new `refreshToken`. The API invalidates
348
+ the earlier refresh token. This mutation needs no `Authorization` header.
329
349
 
330
350
  ## API key authentication
331
351
 
332
- API keys provide long-lived, scoped access to the API. They are typically used for server-to-server integrations and automated workflows.
352
+ An API key gives access to the API for a long time, inside a set of scopes. Most
353
+ callers use an API key for a server-to-server integration or for an automated
354
+ workflow.
333
355
 
334
356
  To authenticate with an API key, include it in the `x-api-key` header:
335
357
 
@@ -337,13 +359,16 @@ To authenticate with an API key, include it in the `x-api-key` header:
337
359
  x-api-key: pk_live_abc123...
338
360
  ```
339
361
 
340
- API keys are scoped to an organization and optionally to a specific project. They carry a defined set of [authorization scopes](./authorization-and-scopes.md) that determine which operations the key can perform.
362
+ An API key belongs to an organization, and it can also belong to one project. It
363
+ carries a set of [authorization scopes](./authorization-and-scopes.md), and those
364
+ scopes decide which operations the key can do.
341
365
 
342
- See [API Keys](/api-keys) for managing keys from the dashboard UI.
366
+ See [API Keys](/api-keys) for how to control a key from the dashboard.
343
367
 
344
- ### Creating an API key
368
+ ### Create an API key
345
369
 
346
- The `apiKeyCreate` mutation creates a new API key. This mutation is only available to session-authenticated users (not other API keys):
370
+ The `apiKeyCreate` mutation creates a new API key. Only a user with a session can
371
+ call it. Another API key cannot:
347
372
 
348
373
  ```graphql
349
374
  mutation {
@@ -358,11 +383,13 @@ mutation {
358
383
  }
359
384
  ```
360
385
 
361
- The full API key string is returned only once in the response. Store it securely; it cannot be retrieved again.
386
+ The response holds the full API key string one time only. Keep it in a secure place, because
387
+ you cannot read it again.
362
388
 
363
- The requested scopes must be a subset of the creating user's scopes. See [Authorization and Scopes](./authorization-and-scopes.md) for more details.
389
+ The scopes that you ask for must all be scopes of the user who creates the key. See
390
+ [Authorization and Scopes](./authorization-and-scopes.md) for more detail.
364
391
 
365
- ### Revoking an API key
392
+ ### Revoke an API key
366
393
 
367
394
  ```graphql
368
395
  mutation {
@@ -373,4 +400,4 @@ mutation {
373
400
  }
374
401
  ```
375
402
 
376
- Revoked keys are immediately invalidated and cannot be used for further requests.
403
+ The API invalidates a revoked key immediately. No later request can use it.
@@ -4,11 +4,14 @@ layout: docs
4
4
 
5
5
  # Authorization and scopes
6
6
 
7
- The Picked API uses a scope-based authorization model. Every authenticated caller (session user or API key) carries a set of scopes that determine which operations they can perform. This guide explains the scope system, roles, and how permissions are resolved.
7
+ The Picked API controls access with scopes. Every authenticated caller carries a set
8
+ of scopes, and those scopes decide which operations the caller can do. A caller is
9
+ either a user with a session or an API key. This guide covers the scopes, the roles,
10
+ and how the API resolves a permission.
8
11
 
9
- ## Scope naming format
12
+ ## The format of a scope name
10
13
 
11
- Scopes follow the `entity/action` convention:
14
+ A scope has the form `entity/action`:
12
15
 
13
16
  ```
14
17
  organization/read
@@ -16,83 +19,87 @@ organization_members/create
16
19
  organization_projects/delete
17
20
  ```
18
21
 
19
- - **entity** — a lowercase name using underscores for multi-word entities (e.g., `organization_members`, `organization_api_keys`)
20
- - **action** — one of `create`, `read`, `update`, or `delete`
22
+ - **entity** — a lowercase name. It uses an underscore between words, as in
23
+ `organization_members` and `organization_api_keys`.
24
+ - **action** — one of `create`, `read`, `update`, or `delete`.
21
25
 
22
- In the GraphQL schema, scopes are represented as the `Scope` enum using uppercase with underscores (e.g., `ORGANIZATION_READ`, `ORGANIZATION_MEMBERS_CREATE`). Both formats refer to the same scope.
26
+ The GraphQL schema holds the scopes in the `Scope` enum. There they are uppercase
27
+ with an underscore between words, as in `ORGANIZATION_READ` and
28
+ `ORGANIZATION_MEMBERS_CREATE`. The two forms name the same scope.
23
29
 
24
30
  ## Full scope list
25
31
 
26
- The following scopes are available:
32
+ These are the scopes:
27
33
 
28
34
  ### Organization
29
35
 
30
36
  | Scope | GraphQL Enum | Description |
31
37
  |-------|-------------|-------------|
32
- | `organization/create` | `ORGANIZATION_CREATE` | Create new organizations |
33
- | `organization/read` | `ORGANIZATION_READ` | View organization details |
34
- | `organization/update` | `ORGANIZATION_UPDATE` | Update organization name, slug, and settings |
38
+ | `organization/create` | `ORGANIZATION_CREATE` | Create an organization |
39
+ | `organization/read` | `ORGANIZATION_READ` | Read the detail of an organization |
40
+ | `organization/update` | `ORGANIZATION_UPDATE` | Update the name, the slug, and the settings of an organization |
35
41
  | `organization/delete` | `ORGANIZATION_DELETE` | Delete an organization |
36
42
 
37
43
  ### Organization members
38
44
 
39
45
  | Scope | GraphQL Enum | Description |
40
46
  |-------|-------------|-------------|
41
- | `organization_members/create` | `ORGANIZATION_MEMBERS_CREATE` | Add members to an organization |
42
- | `organization_members/read` | `ORGANIZATION_MEMBERS_READ` | View organization member list |
43
- | `organization_members/update` | `ORGANIZATION_MEMBERS_UPDATE` | Update member roles |
44
- | `organization_members/delete` | `ORGANIZATION_MEMBERS_DELETE` | Remove members from an organization |
47
+ | `organization_members/create` | `ORGANIZATION_MEMBERS_CREATE` | Add a member to an organization |
48
+ | `organization_members/read` | `ORGANIZATION_MEMBERS_READ` | Read the member list of an organization |
49
+ | `organization_members/update` | `ORGANIZATION_MEMBERS_UPDATE` | Update the role of a member |
50
+ | `organization_members/delete` | `ORGANIZATION_MEMBERS_DELETE` | Remove a member from an organization |
45
51
 
46
52
  ### Organization invitations
47
53
 
48
54
  | Scope | GraphQL Enum | Description |
49
55
  |-------|-------------|-------------|
50
- | `organization_invitations/create` | `ORGANIZATION_INVITATIONS_CREATE` | Send invitations to join an organization |
51
- | `organization_invitations/read` | `ORGANIZATION_INVITATIONS_READ` | View pending invitations |
52
- | `organization_invitations/delete` | `ORGANIZATION_INVITATIONS_DELETE` | Revoke pending invitations |
56
+ | `organization_invitations/create` | `ORGANIZATION_INVITATIONS_CREATE` | Send an invitation to join an organization |
57
+ | `organization_invitations/read` | `ORGANIZATION_INVITATIONS_READ` | Read the invitations that wait for an answer |
58
+ | `organization_invitations/delete` | `ORGANIZATION_INVITATIONS_DELETE` | Revoke an invitation that waits for an answer |
53
59
 
54
60
  ### Organization projects
55
61
 
56
62
  | Scope | GraphQL Enum | Description |
57
63
  |-------|-------------|-------------|
58
- | `organization_projects/create` | `ORGANIZATION_PROJECTS_CREATE` | Create new projects |
59
- | `organization_projects/read` | `ORGANIZATION_PROJECTS_READ` | View project details |
60
- | `organization_projects/update` | `ORGANIZATION_PROJECTS_UPDATE` | Update project settings |
61
- | `organization_projects/delete` | `ORGANIZATION_PROJECTS_DELETE` | Delete projects |
64
+ | `organization_projects/create` | `ORGANIZATION_PROJECTS_CREATE` | Create a project |
65
+ | `organization_projects/read` | `ORGANIZATION_PROJECTS_READ` | Read the detail of a project |
66
+ | `organization_projects/update` | `ORGANIZATION_PROJECTS_UPDATE` | Update the settings of a project |
67
+ | `organization_projects/delete` | `ORGANIZATION_PROJECTS_DELETE` | Delete a project |
62
68
 
63
69
  ### Organization API keys
64
70
 
65
71
  | Scope | GraphQL Enum | Description |
66
72
  |-------|-------------|-------------|
67
- | `organization_api_keys/create` | `ORGANIZATION_API_KEYS_CREATE` | Create new API keys |
68
- | `organization_api_keys/read` | `ORGANIZATION_API_KEYS_READ` | View API keys (prefix only, not the full key) |
69
- | `organization_api_keys/delete` | `ORGANIZATION_API_KEYS_DELETE` | Revoke API keys |
73
+ | `organization_api_keys/create` | `ORGANIZATION_API_KEYS_CREATE` | Create an API key |
74
+ | `organization_api_keys/read` | `ORGANIZATION_API_KEYS_READ` | Read the API keys. This gives the prefix only, and not the full key. |
75
+ | `organization_api_keys/delete` | `ORGANIZATION_API_KEYS_DELETE` | Revoke an API key |
70
76
 
71
77
  ### Organization integrations
72
78
 
73
79
  | Scope | GraphQL Enum | Description |
74
80
  |-------|-------------|-------------|
75
- | `organization_integrations/create` | `ORGANIZATION_INTEGRATIONS_CREATE` | Set up new integrations |
76
- | `organization_integrations/read` | `ORGANIZATION_INTEGRATIONS_READ` | View integration configurations |
77
- | `organization_integrations/update` | `ORGANIZATION_INTEGRATIONS_UPDATE` | Modify integration settings |
78
- | `organization_integrations/delete` | `ORGANIZATION_INTEGRATIONS_DELETE` | Remove integrations |
81
+ | `organization_integrations/create` | `ORGANIZATION_INTEGRATIONS_CREATE` | Set up an integration |
82
+ | `organization_integrations/read` | `ORGANIZATION_INTEGRATIONS_READ` | Read the options of an integration |
83
+ | `organization_integrations/update` | `ORGANIZATION_INTEGRATIONS_UPDATE` | Change the settings of an integration |
84
+ | `organization_integrations/delete` | `ORGANIZATION_INTEGRATIONS_DELETE` | Remove an integration |
79
85
 
80
86
  ### Organization reports
81
87
 
82
88
  | Scope | GraphQL Enum | Description |
83
89
  |-------|-------------|-------------|
84
- | `organization_reports/create` | `ORGANIZATION_REPORTS_CREATE` | Create new reports |
85
- | `organization_reports/read` | `ORGANIZATION_REPORTS_READ` | View reports |
86
- | `organization_reports/update` | `ORGANIZATION_REPORTS_UPDATE` | Update report settings |
87
- | `organization_reports/delete` | `ORGANIZATION_REPORTS_DELETE` | Delete reports |
90
+ | `organization_reports/create` | `ORGANIZATION_REPORTS_CREATE` | Create a report |
91
+ | `organization_reports/read` | `ORGANIZATION_REPORTS_READ` | Read a report |
92
+ | `organization_reports/update` | `ORGANIZATION_REPORTS_UPDATE` | Update the settings of a report |
93
+ | `organization_reports/delete` | `ORGANIZATION_REPORTS_DELETE` | Delete a report |
88
94
 
89
95
  ## Roles
90
96
 
91
- Organization members are assigned one of two roles:
97
+ Each member of an organization holds one of two roles:
92
98
 
93
99
  ### Owner
94
100
 
95
- Owners have full control within their organization. Their default scopes include:
101
+ An owner has full control inside the organization. These are the default scopes of an
102
+ owner:
96
103
 
97
104
  - All `organization/*` scopes (`read`, `update`, `delete`)
98
105
  - All `organization_members/*` scopes
@@ -104,7 +111,8 @@ Owners have full control within their organization. Their default scopes include
104
111
 
105
112
  ### Member
106
113
 
107
- Members have broad access but cannot delete the organization or manage other members. Their default scopes include:
114
+ A member can reach most things, but cannot delete the organization and cannot control
115
+ another member. These are the default scopes of a member:
108
116
 
109
117
  - `organization/read`, `organization/update`
110
118
  - `organization_members/read`
@@ -114,7 +122,7 @@ Members have broad access but cannot delete the organization or manage other mem
114
122
  - All `organization_integrations/*` scopes
115
123
  - `organization_reports/read`
116
124
 
117
- The key differences between owner and member:
125
+ These are the differences between an owner and a member:
118
126
 
119
127
  | Capability | Owner | Member |
120
128
  |-----------|-------|--------|
@@ -123,24 +131,30 @@ The key differences between owner and member:
123
131
  | Remove members | Yes | No |
124
132
  | Update member roles | Yes | No |
125
133
  | Revoke invitations | Yes | No |
126
- | Manage projects and integrations | Yes | Yes |
127
- | Manage API keys | Yes | Yes |
128
- | View reports | Yes | Yes |
134
+ | Control projects and integrations | Yes | Yes |
135
+ | Control API keys | Yes | Yes |
136
+ | Read reports | Yes | Yes |
129
137
 
130
138
  ## How scopes are resolved
131
139
 
132
- When an authenticated request reaches the API, the authorization system resolves scopes as follows:
140
+ When an authenticated request reaches the API, the API resolves the scopes like this:
133
141
 
134
- 1. **Session-authenticated users** — the API looks up the caller's role within the target organization and assigns the default scopes for that role.
135
- 2. **API key requests** — the API uses the scopes that were assigned to the key at creation time. These scopes are always a subset of the creating user's scopes.
142
+ 1. **A user with a session** — the API finds the role of that caller in the target
143
+ organization. It then gives the caller the default scopes of that role.
144
+ 2. **A request with an API key** — the API uses the scopes that the key received when
145
+ somebody created it. Those scopes are always scopes of the user who created the
146
+ key.
136
147
 
137
- For operations that target a specific organization (most queries and mutations), the caller must have the required scope within that organization. For root-level operations like `organizationCreate`, the scope is resolved at the account level.
148
+ Most queries and mutations point at one organization. For those, the caller must hold
149
+ the scope inside that organization. For a root-level operation such as
150
+ `organizationCreate`, the API resolves the scope at the account level.
138
151
 
139
- If the caller lacks the required scope, the API returns an authorization error with a `FORBIDDEN` code. See [Error Handling](./error-handling.md) for details.
152
+ When the caller does not hold the scope that an operation needs, the API returns an
153
+ authorization error with the code `FORBIDDEN`. See [Errors](./error-handling.md).
140
154
 
141
155
  ## Operations and required scopes
142
156
 
143
- The following table maps common operations to the scopes they require:
157
+ This table gives the scope that each common operation needs:
144
158
 
145
159
  ### Queries
146
160
 
@@ -192,7 +206,7 @@ Some mutations do not require organization-level scopes because they operate on
192
206
  | `organizationInvitationAccept` / `organizationInvitationDecline` | Authenticated session (no specific scope) |
193
207
  | `mfaFactorEnroll` / `mfaChallengeSend` / `mfaChallengeVerify` / `mfaFactorUnenroll` | Authenticated session (no specific scope) |
194
208
 
195
- ## Querying scopes
209
+ ## Read your scopes
196
210
 
197
211
  ### Root-level scopes
198
212
 
@@ -259,4 +273,6 @@ Response:
259
273
  }
260
274
  ```
261
275
 
262
- This is useful for building UIs that adapt based on the caller's permissions — for example, hiding a "Delete Organization" button when the caller lacks `ORGANIZATION_DELETE`.
276
+ Use this to build a UI that changes with the permissions of the caller. An example is
277
+ a **Delete Organization** button that the UI hides when the caller does not hold
278
+ `ORGANIZATION_DELETE`.