@picked/client 0.0.1-dev.1785305085063 → 0.0.1-dev.1785908062293

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 (291) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/api-03c5jvVk.js +38 -0
  3. package/dist/api-CQxCVIrm.cjs +1 -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/explanation/conditions-and-the-logic-engine.md +94 -0
  10. package/dist/docs/explanation/feature-flag-allocation.md +176 -0
  11. package/dist/docs/explanation/how-picked-works.md +124 -0
  12. package/dist/docs/explanation/how-pickedql-works.md +76 -0
  13. package/dist/docs/explanation/pages-and-flows.md +64 -0
  14. package/dist/docs/explanation/the-content-model.md +77 -0
  15. package/dist/docs/explanation/the-two-apis.md +68 -0
  16. package/dist/docs/explanation/why-server-side-rendering.md +76 -0
  17. package/dist/docs/explanation/workspaces-and-versions.md +71 -0
  18. package/dist/docs/how-to/add-a-step-field-or-action.md +43 -0
  19. package/dist/docs/{pickedql/examples.md → how-to/analytics/index.md} +53 -28
  20. package/dist/docs/how-to/archive-or-delete-a-workspace.md +46 -0
  21. package/dist/docs/how-to/authenticate-with-a-magic-link.md +40 -0
  22. package/dist/docs/how-to/authenticate-with-a-password.md +51 -0
  23. package/dist/docs/how-to/authenticate-with-an-api-key.md +51 -0
  24. package/dist/docs/how-to/authenticate-with-oauth.md +40 -0
  25. package/dist/docs/how-to/build-a-flow.md +83 -0
  26. package/dist/docs/how-to/connect-the-mcp-server.md +38 -0
  27. package/dist/docs/how-to/create-a-project.md +29 -0
  28. package/dist/docs/how-to/create-an-experience.md +42 -0
  29. package/dist/docs/how-to/create-and-revoke-an-api-key.md +37 -0
  30. package/dist/docs/how-to/debug-with-the-chrome-extension.md +57 -0
  31. package/dist/docs/how-to/define-a-page-layout.md +39 -0
  32. package/dist/docs/how-to/fill-and-publish-a-page.md +50 -0
  33. package/dist/docs/how-to/install-the-gtm-template.md +84 -0
  34. package/dist/docs/how-to/install-the-sdk.md +68 -0
  35. package/dist/docs/how-to/install-the-vite-plugin.md +56 -0
  36. package/dist/docs/how-to/invite-and-remove-members.md +34 -0
  37. package/dist/docs/how-to/preview-a-workspace.md +28 -0
  38. package/dist/docs/how-to/publish-a-workspace.md +30 -0
  39. package/dist/docs/how-to/read-a-feature-flag.md +101 -0
  40. package/dist/docs/how-to/register-a-component.md +55 -0
  41. package/dist/docs/how-to/register-an-action-handler.md +67 -0
  42. package/dist/docs/how-to/render-a-step-form.md +132 -0
  43. package/dist/docs/how-to/render-an-unpublished-preview.md +41 -0
  44. package/dist/docs/how-to/reuse-a-section.md +37 -0
  45. package/dist/docs/how-to/reuse-a-step-field-or-action.md +28 -0
  46. package/dist/docs/how-to/roll-back-a-published-version.md +26 -0
  47. package/dist/docs/how-to/run-an-ab-test.md +49 -0
  48. package/dist/docs/how-to/run-code-on-a-form-submission.md +125 -0
  49. package/dist/docs/how-to/server-render-a-page.md +81 -0
  50. package/dist/docs/how-to/set-a-content-security-policy.md +32 -0
  51. package/dist/docs/how-to/set-up-mfa.md +69 -0
  52. package/dist/docs/how-to/upload-and-use-an-asset.mdx +73 -0
  53. package/dist/docs/how-to/validate-a-field.md +52 -0
  54. package/dist/docs/how-to/write-a-condition.md +45 -0
  55. package/dist/docs/how-to/write-a-predicate.md +60 -0
  56. package/dist/docs/index.md +41 -59
  57. package/dist/docs/reference/dashboard/actions.mdx +53 -0
  58. package/dist/docs/reference/dashboard/api-keys.mdx +37 -0
  59. package/dist/docs/reference/dashboard/conditions.mdx +42 -0
  60. package/dist/docs/reference/dashboard/content/asset-library.mdx +63 -0
  61. package/dist/docs/reference/dashboard/content/content-entries.mdx +44 -0
  62. package/dist/docs/reference/dashboard/content/layouts.mdx +62 -0
  63. package/dist/docs/reference/dashboard/content/pages.mdx +35 -0
  64. package/dist/docs/reference/dashboard/content/sections.mdx +28 -0
  65. package/dist/docs/reference/dashboard/experiences.mdx +51 -0
  66. package/dist/docs/reference/dashboard/features.mdx +114 -0
  67. package/dist/docs/reference/dashboard/fields.mdx +100 -0
  68. package/dist/docs/reference/dashboard/flow-builder/canvas.mdx +58 -0
  69. package/dist/docs/reference/dashboard/flow-builder/condition-builder.md +57 -0
  70. package/dist/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +72 -0
  71. package/dist/docs/reference/dashboard/flow-builder/nodes.md +63 -0
  72. package/dist/docs/reference/dashboard/projects.mdx +44 -0
  73. package/dist/docs/reference/dashboard/reports.mdx +43 -0
  74. package/dist/docs/reference/dashboard/steps.mdx +37 -0
  75. package/dist/docs/reference/dashboard/team-management.md +29 -0
  76. package/dist/docs/reference/dashboard/workspace-versioning.mdx +30 -0
  77. package/dist/docs/reference/dashboard/workspaces.mdx +76 -0
  78. package/dist/docs/{delivery-api → reference/delivery-api}/experience-content.md +17 -5
  79. package/dist/docs/reference/delivery-api/index.md +45 -0
  80. package/dist/docs/reference/delivery-api/preview-caching-crawling.md +79 -0
  81. package/dist/docs/{delivery-api → reference/delivery-api}/project-config.md +15 -6
  82. package/dist/docs/reference/glossary.md +173 -0
  83. package/dist/docs/reference/management-api/authentication.md +74 -0
  84. package/dist/docs/{api → reference/management-api}/authorization-and-scopes.md +70 -47
  85. package/dist/docs/reference/management-api/error-handling.md +233 -0
  86. package/dist/docs/{api → reference/management-api}/pagination.md +36 -20
  87. package/dist/docs/reference/pickedql/data-sources.md +174 -0
  88. package/dist/docs/reference/pickedql/dimensions.md +87 -0
  89. package/dist/docs/{pickedql → reference/pickedql}/filtering.md +17 -6
  90. package/dist/docs/reference/pickedql/index.md +18 -0
  91. package/dist/docs/reference/pickedql/schema.md +172 -0
  92. package/dist/docs/reference/pickedql/virtual-functions.md +237 -0
  93. package/dist/docs/reference/sdk/actions.md +30 -0
  94. package/dist/docs/{sdk → reference/sdk}/conditions.md +15 -5
  95. package/dist/docs/reference/sdk/content-security-policy.md +21 -0
  96. package/dist/docs/reference/sdk/experiences.md +51 -0
  97. package/dist/docs/reference/sdk/features.md +233 -0
  98. package/dist/docs/reference/sdk/fields.md +209 -0
  99. package/dist/docs/reference/sdk/index.md +68 -0
  100. package/dist/docs/{sdk → reference/sdk}/plugins/create-experience.md +25 -34
  101. package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +74 -0
  102. package/dist/docs/reference/sdk/plugins/index.md +29 -0
  103. package/dist/docs/{sdk → reference/sdk}/plugins/window-object.md +6 -0
  104. package/dist/docs/reference/sdk/predicates.md +43 -0
  105. package/dist/docs/reference/sdk/ssr/index.md +33 -0
  106. package/dist/docs/reference/sdk/ssr/rendering-and-hydration.md +103 -0
  107. package/dist/docs/reference/sdk/ssr/serialize.md +77 -0
  108. package/dist/docs/reference/sdk/ssr/slots-and-placements.md +59 -0
  109. package/dist/docs/reference/sdk/steps.md +87 -0
  110. package/dist/docs/reference/tools/chrome-extension.md +16 -0
  111. package/dist/docs/reference/tools/image-optimisation-service.md +104 -0
  112. package/dist/docs/reference/tools/mcp.md +88 -0
  113. package/dist/docs/reference/tools/vite-plugin.md +88 -0
  114. package/dist/docs/tutorials/first-api-call.md +228 -0
  115. package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +143 -0
  116. package/dist/docs/tutorials/first-experience.mdx +255 -0
  117. package/dist/docs/tutorials/first-server-rendered-page.mdx +186 -0
  118. package/dist/{dom-BwmTHeT7.js → dom-BqcToNL0.js} +1 -3
  119. package/dist/{dom-CDrHc_j9.cjs → dom-DlLH3FxV.cjs} +1 -1
  120. package/dist/esm/form/index.js +2 -4
  121. package/dist/esm/index.js +225 -186
  122. package/dist/esm/plugins/dom-observer/index.js +1 -1
  123. package/dist/esm/plugins/dynamic-experiences/index.js +3 -3
  124. package/dist/esm/preview/index.js +1 -1
  125. package/dist/esm/server/index.js +33 -31
  126. package/dist/{experience-instance-DOJShRk5.js → experience-instance-DGk11d8a.js} +3 -3
  127. package/dist/experience-instance-Dej3P1sE.cjs +1 -0
  128. package/dist/plugin-CHOVsx7Z.js +287 -0
  129. package/dist/plugin-DsaGXQHx.cjs +1 -0
  130. package/dist/{preview-channel-DW9J8t4B.js → preview-channel-CSr96XAo.js} +1 -1
  131. package/dist/{protocol-DSqOlW2r.js → protocol-C5KkkiZc.js} +1 -1
  132. package/dist/types/client.d.ts +7 -6
  133. package/dist/types/data-source/api.d.ts +60 -0
  134. package/dist/types/data-source/api.d.ts.map +1 -0
  135. package/dist/types/data-source/provider.d.ts +97 -0
  136. package/dist/types/data-source/provider.d.ts.map +1 -0
  137. package/dist/types/entities/action/action.d.ts +5 -4
  138. package/dist/types/entities/action/action.d.ts.map +1 -1
  139. package/dist/types/entities/component/component.d.ts +6 -5
  140. package/dist/types/entities/component/component.d.ts.map +1 -1
  141. package/dist/types/entities/condition/condition.d.ts +5 -5
  142. package/dist/types/entities/content/content.d.ts +4 -3
  143. package/dist/types/entities/experience/experience.d.ts +11 -10
  144. package/dist/types/entities/experience/experience.d.ts.map +1 -1
  145. package/dist/types/entities/experience-instance/experience-instance.d.ts +10 -9
  146. package/dist/types/entities/feature/feature.d.ts +19 -2
  147. package/dist/types/entities/feature/feature.d.ts.map +1 -1
  148. package/dist/types/entities/field/field.d.ts +7 -6
  149. package/dist/types/entities/framework/framework.d.ts +7 -6
  150. package/dist/types/entities/framework/framework.d.ts.map +1 -1
  151. package/dist/types/entities/history/history.d.ts +6 -6
  152. package/dist/types/entities/plugin/plugin.d.ts +3 -2
  153. package/dist/types/entities/plugin/plugin.d.ts.map +1 -1
  154. package/dist/types/entities/predicate/predicate.d.ts +4 -3
  155. package/dist/types/entities/predicate/predicate.d.ts.map +1 -1
  156. package/dist/types/entities/response/response-validation.d.ts +3 -2
  157. package/dist/types/entities/response/response.d.ts +12 -11
  158. package/dist/types/entities/session/session.d.ts +2 -1
  159. package/dist/types/entities/step/step.d.ts +6 -5
  160. package/dist/types/exports.d.ts +2 -1
  161. package/dist/types/exports.d.ts.map +1 -1
  162. package/dist/types/form/build-responses.d.ts +2 -1
  163. package/dist/types/form/create-field-evaluator.d.ts +4 -3
  164. package/dist/types/form/create-field-validation.d.ts +5 -4
  165. package/dist/types/form/create-form.d.ts +7 -6
  166. package/dist/types/form/create-submit-pipeline.d.ts +7 -6
  167. package/dist/types/form/get-step-fields.d.ts +3 -2
  168. package/dist/types/lifecycle/condition-selection.d.ts +14 -4
  169. package/dist/types/lifecycle/lifecycle.d.ts +4 -3
  170. package/dist/types/lifecycle/rules-logic.d.ts +4 -3
  171. package/dist/types/lifecycle/state-snapshot.d.ts +4 -3
  172. package/dist/types/picked.d.ts +79 -62
  173. package/dist/types/picked.d.ts.map +1 -1
  174. package/dist/types/ping.d.ts +1 -1
  175. package/dist/types/ping.d.ts.map +1 -1
  176. package/dist/types/plugins/create-experience/create-experience.d.ts +9 -8
  177. package/dist/types/plugins/create-experience/create-experience.d.ts.map +1 -1
  178. package/dist/types/plugins/create-experience/plugin.d.ts +3 -2
  179. package/dist/types/plugins/create-experience/plugin.d.ts.map +1 -1
  180. package/dist/types/plugins/create-experience/serialization.d.ts.map +1 -1
  181. package/dist/types/plugins/dom-observer/plugin.d.ts +1 -1
  182. package/dist/types/plugins/dynamic-experiences/hash.d.ts +40 -5
  183. package/dist/types/plugins/dynamic-experiences/hash.d.ts.map +1 -1
  184. package/dist/types/plugins/dynamic-experiences/index.d.ts +2 -0
  185. package/dist/types/plugins/dynamic-experiences/index.d.ts.map +1 -1
  186. package/dist/types/plugins/dynamic-experiences/plugin.d.ts +4 -36
  187. package/dist/types/plugins/dynamic-experiences/plugin.d.ts.map +1 -1
  188. package/dist/types/plugins/dynamic-experiences/types.d.ts +42 -11
  189. package/dist/types/plugins/dynamic-experiences/types.d.ts.map +1 -1
  190. package/dist/types/plugins/experience-browser-storage/plugin.d.ts +1 -1
  191. package/dist/types/plugins/experience-browser-storage/plugin.d.ts.map +1 -1
  192. package/dist/types/plugins/history-browser-storage/plugin.d.ts +1 -1
  193. package/dist/types/plugins/history-browser-storage/plugin.d.ts.map +1 -1
  194. package/dist/types/plugins/responses-browser-storage/plugin.d.ts +1 -1
  195. package/dist/types/plugins/responses-browser-storage/plugin.d.ts.map +1 -1
  196. package/dist/types/plugins/responses-indexeddb/plugin.d.ts +1 -1
  197. package/dist/types/plugins/single-page-app/plugin.d.ts +1 -1
  198. package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
  199. package/dist/types/plugins/web-components/plugin.d.ts +2 -1
  200. package/dist/types/plugins/window-object/plugin.d.ts +2 -2
  201. package/dist/types/preview-channel.d.ts +5 -1
  202. package/dist/types/preview-receiver/index.d.ts +18 -1
  203. package/dist/types/preview-receiver/protocol.d.ts +10 -1
  204. package/dist/types/server/index.d.ts +3 -3
  205. package/dist/types/server/serialize.d.ts +8 -2
  206. package/dist/types/server/serialize.d.ts.map +1 -1
  207. package/dist/types/utils/dom.d.ts +2 -1
  208. package/dist/types/utils/events.d.ts +6 -6
  209. package/dist/types/utils/events.d.ts.map +1 -1
  210. package/dist/types/utils/global-obj.d.ts +1 -1
  211. package/dist/types/utils/global-obj.d.ts.map +1 -1
  212. package/dist/types/utils/id.d.ts.map +1 -1
  213. package/dist/types/utils/logger.d.ts +2 -1
  214. package/dist/types/utils/logger.d.ts.map +1 -1
  215. package/dist/types/utils/node-tree/get-next-node-from-action.d.ts +2 -1
  216. package/dist/types/utils/node-tree/get-next-node-from-condition.d.ts +2 -1
  217. package/dist/types/utils/node-tree/get-next-node.d.ts +1 -1
  218. package/dist/types/utils/node-tree/get-next-node.d.ts.map +1 -1
  219. package/dist/types/utils/node-tree/get-origin-node.d.ts +1 -1
  220. package/dist/types/utils/node-tree/get-origin-node.d.ts.map +1 -1
  221. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts +1 -1
  222. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts.map +1 -1
  223. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts +1 -1
  224. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts.map +1 -1
  225. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts +1 -1
  226. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts.map +1 -1
  227. package/dist/types/utils/nodes.d.ts +1 -1
  228. package/dist/types/utils/picked-config.d.ts +2 -1
  229. package/dist/types/utils/rehydrate-scripts.d.ts +6 -0
  230. package/dist/types/utils/rehydrate-scripts.d.ts.map +1 -1
  231. package/dist/types/utils/rules-logic.d.ts +6 -2
  232. package/dist/types/utils/storage.d.ts +1 -1
  233. package/dist/types/utils/storage.d.ts.map +1 -1
  234. package/package.json +22 -23
  235. package/dist/api-CPL40b7A.js +0 -40
  236. package/dist/api-Dz5rgRgQ.cjs +0 -1
  237. package/dist/docs/actions.mdx +0 -78
  238. package/dist/docs/api/authentication.md +0 -376
  239. package/dist/docs/api/error-handling.md +0 -211
  240. package/dist/docs/api/index.md +0 -197
  241. package/dist/docs/api-keys.mdx +0 -40
  242. package/dist/docs/chrome-extension.md +0 -51
  243. package/dist/docs/conditions.mdx +0 -59
  244. package/dist/docs/content/asset-library.mdx +0 -93
  245. package/dist/docs/content/content-entries.mdx +0 -30
  246. package/dist/docs/content/layouts.mdx +0 -70
  247. package/dist/docs/content/pages.mdx +0 -67
  248. package/dist/docs/content/sections.mdx +0 -33
  249. package/dist/docs/delivery-api/index.md +0 -46
  250. package/dist/docs/delivery-api/preview-caching-crawling.md +0 -59
  251. package/dist/docs/experiences.mdx +0 -42
  252. package/dist/docs/features.mdx +0 -58
  253. package/dist/docs/fields.mdx +0 -79
  254. package/dist/docs/flow-builder/building-flows.md +0 -61
  255. package/dist/docs/flow-builder/condition-builder.md +0 -54
  256. package/dist/docs/flow-builder/keyboard-shortcuts.md +0 -66
  257. package/dist/docs/flow-builder/nodes.md +0 -43
  258. package/dist/docs/flow-builder/overview.mdx +0 -50
  259. package/dist/docs/gtm-template.md +0 -69
  260. package/dist/docs/guides/build-a-personalized-page.mdx +0 -143
  261. package/dist/docs/image-optimisation-service.md +0 -80
  262. package/dist/docs/mcp.md +0 -120
  263. package/dist/docs/pickedql/data-sources.md +0 -145
  264. package/dist/docs/pickedql/dimensions.md +0 -65
  265. package/dist/docs/pickedql/index.md +0 -36
  266. package/dist/docs/pickedql/schema.md +0 -156
  267. package/dist/docs/pickedql/virtual-functions.md +0 -204
  268. package/dist/docs/projects.mdx +0 -37
  269. package/dist/docs/reports.mdx +0 -18
  270. package/dist/docs/sdk/actions.md +0 -66
  271. package/dist/docs/sdk/content-security-policy.md +0 -32
  272. package/dist/docs/sdk/experiences.md +0 -46
  273. package/dist/docs/sdk/features.md +0 -212
  274. package/dist/docs/sdk/fields.md +0 -263
  275. package/dist/docs/sdk/index.md +0 -83
  276. package/dist/docs/sdk/plugins/dynamic-experiences.md +0 -58
  277. package/dist/docs/sdk/plugins/index.md +0 -9
  278. package/dist/docs/sdk/predicates.md +0 -112
  279. package/dist/docs/sdk/ssr/index.md +0 -62
  280. package/dist/docs/sdk/ssr/rendering-and-hydration.md +0 -141
  281. package/dist/docs/sdk/ssr/serialize.md +0 -86
  282. package/dist/docs/sdk/ssr/slots-and-placements.md +0 -35
  283. package/dist/docs/sdk/steps.md +0 -434
  284. package/dist/docs/steps.mdx +0 -44
  285. package/dist/docs/team-management.md +0 -40
  286. package/dist/docs/vite-plugin.md +0 -82
  287. package/dist/docs/workspace-versioning.mdx +0 -28
  288. package/dist/docs/workspaces.mdx +0 -102
  289. package/dist/experience-instance-DurC3pE-.cjs +0 -1
  290. package/dist/plugin-CFXwbXeM.js +0 -247
  291. package/dist/plugin-m4qekgtA.cjs +0 -1
@@ -1,211 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Error handling
6
-
7
- The Picked API returns errors using the standard GraphQL error format. This guide covers the error response shape, all error codes, and practical strategies for handling errors.
8
-
9
- ## Error response shape
10
-
11
- When an operation fails, the API returns an `errors` array in the response body. Each error object contains:
12
-
13
- ```json
14
- {
15
- "data": null,
16
- "errors": [
17
- {
18
- "message": "A human-readable description of the error",
19
- "path": ["mutationName"],
20
- "extensions": {
21
- "code": "ERROR_CODE"
22
- }
23
- }
24
- ]
25
- }
26
- ```
27
-
28
- | Field | Description |
29
- |-------|-------------|
30
- | `message` | A human-readable error description. Suitable for logging but not for programmatic handling. |
31
- | `path` | The path to the field in the query that caused the error. |
32
- | `extensions.code` | A machine-readable error code. Use this for programmatic error handling. |
33
-
34
- Multiple errors may appear in a single response. The `data` field may be `null` if the entire operation failed, or it may contain partial data if only some fields failed.
35
-
36
- ## Authentication error codes
37
-
38
- These errors relate to session creation, account management, OAuth, magic links, password operations, and MFA. They map to the `AuthErrorCode` enum in the schema.
39
-
40
- | Code | Description |
41
- |------|-------------|
42
- | `INVALID_CREDENTIALS` | The email/password combination is incorrect. |
43
- | `EMAIL_NOT_CONFIRMED` | The account exists but the email address has not been verified. See [Authentication](/api/authentication#email-verification). |
44
- | `USER_NOT_FOUND` | No account exists with the provided email address. |
45
- | `USER_ALREADY_EXISTS` | An account with this email already exists. Returned during account creation. |
46
- | `WEAK_PASSWORD` | The provided password does not meet strength requirements. |
47
- | `INVALID_TOKEN` | The token (verification, reset, or magic link) is invalid or malformed. |
48
- | `TOKEN_EXPIRED` | The token has expired. The caller should request a new one. |
49
- | `MFA_CHALLENGE_FAILED` | The MFA verification code is incorrect. |
50
- | `MFA_FACTOR_NOT_FOUND` | The specified MFA factor does not exist or does not belong to the caller. |
51
- | `OAUTH_PROVIDER_ERROR` | An error occurred communicating with the OAuth provider (e.g., Google). |
52
- | `RATE_LIMITED` | Too many requests in a short period. The caller should wait and retry. |
53
-
54
- ### Example: invalid credentials
55
-
56
- ```json
57
- {
58
- "data": {
59
- "sessionCreate": {
60
- "session": null,
61
- "requiresMfa": false,
62
- "mfaFactors": null
63
- }
64
- },
65
- "errors": [
66
- {
67
- "message": "Invalid credentials",
68
- "path": ["sessionCreate"],
69
- "extensions": {
70
- "code": "INVALID_CREDENTIALS"
71
- }
72
- }
73
- ]
74
- }
75
- ```
76
-
77
- ## Authorization error codes
78
-
79
- Authorization errors occur when the caller lacks the required [scope](./authorization-and-scopes.md) for an operation.
80
-
81
- | Code | Description |
82
- |------|-------------|
83
- | `UNAUTHORIZED` | No valid authentication was provided. The request is missing the `Authorization` header or the `x-api-key` header, or the token/key is invalid. |
84
- | `FORBIDDEN` | The caller is authenticated but does not have the required scope for the operation. |
85
-
86
- ### Example: insufficient scope
87
-
88
- A caller with only `organization/read` attempting to delete an organization receives:
89
-
90
- ```json
91
- {
92
- "data": {
93
- "organizationDelete": null
94
- },
95
- "errors": [
96
- {
97
- "message": "Insufficient permissions",
98
- "path": ["organizationDelete"],
99
- "extensions": {
100
- "code": "FORBIDDEN"
101
- }
102
- }
103
- ]
104
- }
105
- ```
106
-
107
- ## Organization, member, and invitation error codes
108
-
109
- These errors relate to organization management, member operations, and invitation workflows. They map to the `ErrorCode` enum in the schema.
110
-
111
- ### Organization errors
112
-
113
- | Code | Description |
114
- |------|-------------|
115
- | `ORGANIZATION_NOT_FOUND` | The specified organization does not exist or the caller does not have access to it. |
116
- | `ORGANIZATION_ALREADY_EXISTS` | An organization with this name already exists. |
117
- | `SLUG_ALREADY_EXISTS` | The requested slug is already in use by another organization. |
118
- | `INVALID_SLUG` | The slug contains invalid characters. Slugs must be lowercase alphanumeric with hyphens. |
119
-
120
- ### Member errors
121
-
122
- | Code | Description |
123
- |------|-------------|
124
- | `MEMBER_NOT_FOUND` | The specified user is not a member of the organization. |
125
- | `MEMBER_ALREADY_EXISTS` | The user is already a member of the organization. |
126
- | `CANNOT_REMOVE_PRIMARY_OWNER` | The primary owner of an organization cannot be removed. |
127
- | `CANNOT_CHANGE_OWN_ROLE` | A member cannot change their own role. Another owner must perform this action. |
128
-
129
- ### Invitation errors
130
-
131
- | Code | Description |
132
- |------|-------------|
133
- | `INVITATION_NOT_FOUND` | The specified invitation does not exist. |
134
- | `INVITATION_EXPIRED` | The invitation has expired and can no longer be accepted. |
135
- | `INVITATION_ALREADY_ACCEPTED` | The invitation has already been accepted. |
136
-
137
- ### Project errors
138
-
139
- | Code | Description |
140
- |------|-------------|
141
- | `PROJECT_NOT_FOUND` | The specified project does not exist or the caller does not have access. |
142
-
143
- ### General errors
144
-
145
- | Code | Description |
146
- |------|-------------|
147
- | `VALIDATION_ERROR` | The input failed validation. Check the `message` field for details about which field is invalid. |
148
- | `INTERNAL_ERROR` | An unexpected server error occurred. Retry the request or contact support if the issue persists. |
149
-
150
- ## Handling errors in practice
151
-
152
- ### Check for errors first
153
-
154
- Every response should be checked for the presence of an `errors` array before processing `data`:
155
-
156
- ```javascript
157
- const response = await fetch('/graphql', {
158
- method: 'POST',
159
- headers: {
160
- 'Content-Type': 'application/json',
161
- 'Authorization': `Bearer ${accessToken}`,
162
- },
163
- body: JSON.stringify({ query, variables }),
164
- });
165
-
166
- const result = await response.json();
167
-
168
- if (result.errors) {
169
- for (const error of result.errors) {
170
- const code = error.extensions?.code;
171
-
172
- switch (code) {
173
- case 'UNAUTHORIZED':
174
- // Redirect to login
175
- break;
176
- case 'FORBIDDEN':
177
- // Show a permissions error
178
- break;
179
- case 'RATE_LIMITED':
180
- // Wait and retry
181
- break;
182
- default:
183
- // Log or display the error message
184
- console.error(error.message);
185
- }
186
- }
187
- }
188
- ```
189
-
190
- ### Refresh expired tokens
191
-
192
- If a request returns `UNAUTHORIZED` and the caller has a refresh token, attempt a [session refresh](/api/authentication#session-refresh) before treating it as a login failure:
193
-
194
- ```javascript
195
- if (code === 'UNAUTHORIZED' && refreshToken) {
196
- const refreshResult = await sessionRefresh(refreshToken);
197
- if (refreshResult.session) {
198
- // Retry the original request with the new access token
199
- } else {
200
- // Redirect to login
201
- }
202
- }
203
- ```
204
-
205
- ### Handle partial data
206
-
207
- GraphQL can return partial data alongside errors. For example, a query that fetches an organization and its members might succeed for the organization but fail for the members if the caller lacks `organization_members/read`. In this case, the response contains both `data` (with the organization) and `errors` (for the members field). Always check both.
208
-
209
- ### Retry transient failures
210
-
211
- `INTERNAL_ERROR` and `RATE_LIMITED` are transient. For `RATE_LIMITED`, implement exponential backoff before retrying. For `INTERNAL_ERROR`, a single retry is usually sufficient.
@@ -1,197 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Getting started
6
-
7
- This guide walks you through your first interactions with the Picked GraphQL API, from sending a simple ping to making authenticated queries and mutations.
8
-
9
- :::note
10
- This reference covers the authenticated GraphQL management API. To serve your published config and page content to your app, use the public, read-only [Delivery API](/delivery-api) instead.
11
- :::
12
-
13
- ## Playground
14
-
15
- Explore the API and run queries interactively in the [GraphQL Playground](https://api.picked.app/api/graphql).
16
-
17
- ## API endpoint
18
-
19
- All requests go to a single endpoint:
20
-
21
- ```
22
- POST https://api.picked.app/api/graphql
23
- ```
24
-
25
- Every request must use the `POST` method with a JSON body containing a `query` field and an optional `variables` field:
26
-
27
- ```json
28
- {
29
- "query": "query { ... }",
30
- "variables": { }
31
- }
32
- ```
33
-
34
- Set the `Content-Type` header to `application/json` on every request.
35
-
36
- ```bash
37
- curl -X POST https://api.picked.app/api/graphql \
38
- -H "Content-Type: application/json" \
39
- -d '{"query": "{ ping }"}'
40
- ```
41
-
42
- ## Ping the API
43
-
44
- Verify that the API is reachable with the `ping` query. This query does not require authentication.
45
-
46
- ```graphql
47
- query {
48
- ping
49
- }
50
- ```
51
-
52
- Response:
53
-
54
- ```json
55
- {
56
- "data": {
57
- "ping": "pong"
58
- }
59
- }
60
- ```
61
-
62
- If you receive this response, the API is up and ready.
63
-
64
- ## Authenticate
65
-
66
- Most operations require an access token. You obtain one by creating a session with your email and password.
67
-
68
- ```graphql
69
- mutation {
70
- sessionCreate(input: {
71
- email: "you@example.com"
72
- password: "your-password"
73
- }) {
74
- session {
75
- accessToken
76
- refreshToken
77
- expiresAt
78
- }
79
- requiresMfa
80
- }
81
- }
82
- ```
83
-
84
- A successful response returns a `Session` containing an `accessToken` and a `refreshToken`:
85
-
86
- ```json
87
- {
88
- "data": {
89
- "sessionCreate": {
90
- "session": {
91
- "accessToken": "eyJhbGciOiJIUzI1NiIs...",
92
- "refreshToken": "v1.refresh-token...",
93
- "expiresAt": "2025-01-15T12:00:00Z"
94
- },
95
- "requiresMfa": false
96
- }
97
- }
98
- }
99
- ```
100
-
101
- If `requiresMfa` is `true`, you need to complete the MFA challenge before receiving a session. See the [Authentication](./authentication.md) guide for details.
102
-
103
- For server-to-server integrations, prefer [API key authentication](/api/authentication#api-key-authentication) over session tokens.
104
-
105
- ## Make an authenticated query
106
-
107
- Pass the access token in the `Authorization` header as a Bearer token:
108
-
109
- ```
110
- Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
111
- ```
112
-
113
- Now you can query resources that require authentication. For example, fetch your user profile:
114
-
115
- ```graphql
116
- query {
117
- user {
118
- id
119
- email
120
- createdAt
121
- organizations(first: 5) {
122
- edges {
123
- node {
124
- id
125
- name
126
- }
127
- }
128
- }
129
- }
130
- }
131
- ```
132
-
133
- ## Make a mutation
134
-
135
- Mutations follow the same pattern: send a `POST` request with the `Authorization` header. For example, create an organization:
136
-
137
- ```graphql
138
- mutation {
139
- organizationCreate(input: {
140
- name: "My Company"
141
- slug: "my-company"
142
- }) {
143
- organization {
144
- id
145
- name
146
- slug
147
- }
148
- }
149
- }
150
- ```
151
-
152
- Response:
153
-
154
- ```json
155
- {
156
- "data": {
157
- "organizationCreate": {
158
- "organization": {
159
- "id": "org_abc123",
160
- "name": "My Company",
161
- "slug": "my-company"
162
- }
163
- }
164
- }
165
- }
166
- ```
167
-
168
- Every mutation accepts an `input` argument and returns a payload object. The payload contains the created or updated resource on success, or errors in the top-level `errors` array on failure.
169
-
170
- ## Error handling basics
171
-
172
- When something goes wrong, the API returns errors in the standard GraphQL `errors` array:
173
-
174
- ```json
175
- {
176
- "data": null,
177
- "errors": [
178
- {
179
- "message": "Invalid credentials",
180
- "extensions": {
181
- "code": "INVALID_CREDENTIALS"
182
- }
183
- }
184
- ]
185
- }
186
- ```
187
-
188
- Check the `extensions.code` field for a machine-readable error code you can use to handle specific failures programmatically. See the [Error Handling](./error-handling.md) guide for the full list of error codes.
189
-
190
- ## Next steps
191
-
192
- Now that you can authenticate and make requests, explore these guides to go deeper:
193
-
194
- - [Authentication](./authentication.md) — email/password, OAuth, magic links, MFA, API keys, and session management
195
- - [Authorization and Scopes](./authorization-and-scopes.md) — understand what each role can access and how scopes control permissions
196
- - [Pagination](./pagination.md) — navigate large result sets with cursor-based pagination
197
- - [Error Handling](./error-handling.md) — handle every error code the API can return
@@ -1,40 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- import { Screenshot } from '../../components/Screenshot'
6
-
7
- # API keys
8
-
9
- API keys let you access Picked's API programmatically. Use them for server-side integrations or CI/CD workflows.
10
-
11
- <Screenshot
12
- route="/{orgSlug}/api-keys"
13
- alt="The API keys list for an organization on the Picked dashboard"
14
- />
15
-
16
- ## Create an API key
17
-
18
- 1. Open your organization.
19
- 2. Click **API Keys**.
20
- 3. Click **Create Key**.
21
- 4. Enter a description.
22
- 5. Click **Create**.
23
-
24
- Copy the key immediately — it won't be shown again.
25
-
26
- ## Using an API key
27
-
28
- Include your API key in the `Authorization` header when making requests to the [Picked API](/api).
29
-
30
- ```
31
- Authorization: Bearer your-api-key
32
- ```
33
-
34
- ## Scopes
35
-
36
- API keys can be scoped to limit what they can access. When creating a key, select the scopes that match your integration's needs. A key can only perform actions allowed by its assigned scopes.
37
-
38
- ## Revoke a key
39
-
40
- Revoke a key at any time from the API keys list. Click the revoke button next to the key you want to disable. Revoked keys stop working immediately.
@@ -1,51 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Chrome Extension
6
-
7
- The Picked Developer Tools extension adds a Picked panel to Chrome DevTools for inspecting and debugging your Picked integration on any page running the SDK.
8
-
9
- ![Picked Developer Tools](/chrome-extension-screenshot.jpg)
10
-
11
- ## Installation
12
-
13
- Install from the [Chrome Web Store](https://chromewebstore.google.com/detail/picked-developer-tools/nimmdamgnhlhdpngnalkpmnleebngidh).
14
-
15
- ## Setup
16
-
17
- Add the `svelteDevtoolsPlugin` to your Picked client so the extension can connect to the SDK.
18
-
19
- ```typescript
20
- import { createPicked } from '@picked/client'
21
- import { svelteDevtoolsPlugin } from '@picked/svelte/plugins/devtools'
22
-
23
- const picked = createPicked({
24
- projectId: 'your-project-id',
25
- plugins: [
26
- svelteDevtoolsPlugin(),
27
- ],
28
- })
29
- ```
30
-
31
- ## Custom Tools
32
-
33
- You can extend the Developer Tools with your own project-specific tools, surfaced under a **Custom Tools** tab. Each tool is a framework-adapted component — authored with the same `adaptReactComponent` / `adaptSvelteComponent` helpers you already use — so you can build it in your app's framework and it receives the live Picked client exactly like an experience component does (React: `usePicked()`; Svelte: `getPicked()`). Tools can both read client state and call client methods.
34
-
35
- ```typescript
36
- import { createPicked } from '@picked/client'
37
- import { adaptReactComponent } from '@picked/react'
38
- import { svelteDevtoolsPlugin } from '@picked/svelte/plugins/devtools'
39
- import MyTool from './MyTool'
40
-
41
- const picked = createPicked({
42
- projectId: 'your-project-id',
43
- plugins: [
44
- svelteDevtoolsPlugin({
45
- customTools: [{ id: 'my-tool', label: 'My Tool', component: adaptReactComponent(MyTool) }],
46
- }),
47
- ],
48
- })
49
- ```
50
-
51
- The Developer Tools shell is rendered with Svelte, so a tool's framework must also be registered on the client. A React app needs `reactFrameworkPlugin` (for the tool) alongside the Svelte framework and `svelteDevtoolsPlugin` (for the shell). If a tool's framework isn't registered, its tab shows a warning instead of rendering.
@@ -1,59 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- import { Screenshot } from '../../components/Screenshot'
6
-
7
- # Conditions
8
-
9
- A condition evaluates logic and branches the flow into two paths — one for when the condition is true, another for when it's false.
10
-
11
- <Screenshot
12
- route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/conditions"
13
- alt="The conditions list for a workspace on the Picked dashboard"
14
- />
15
-
16
- ## Create a condition
17
-
18
- 1. Open your project.
19
- 2. Click **Conditions** in the sidebar.
20
- 3. Click **New Condition**.
21
- 4. Enter a name and key.
22
- 5. Click **Create**.
23
-
24
- ## Configure a condition
25
-
26
- **Name**: The display name shown in the dashboard. Not visible to visitors.
27
-
28
- **Key**: The programmatic identifier. Set once, can't change. Not visible to visitors.
29
-
30
- ## Define logic
31
-
32
- Select a condition node in the flow builder to open its inspector. The **Logic** section contains a visual [condition builder](/flow-builder/condition-builder).
33
-
34
- The condition builder lets you create rules using AND/OR groups. Each rule compares a data source against an operator and a target value.
35
-
36
- ### Available data sources
37
-
38
- **Responses** — values visitors have submitted through form fields. For example, check if a visitor entered a specific email domain or selected a particular option.
39
-
40
- **Actions** — references to actions that have been triggered during the flow.
41
-
42
- **Features** — the state of feature flags in your project. Branch based on which variant a visitor is assigned to.
43
-
44
- **Location** — properties of the visitor's current page URL, including pathname, search parameters, hostname, and hash. For example, show different content based on which page the visitor is on.
45
-
46
- ### Example
47
-
48
- To branch based on a visitor's country selection:
49
-
50
- 1. Add a rule: **Responses → country** equals `US`.
51
- 2. The green (true) path handles US visitors. The red (false) path handles everyone else.
52
-
53
- To combine multiple conditions, create an AND or OR group and add rules within it.
54
-
55
- ## Branching
56
-
57
- In the flow builder, condition nodes have two output handles. The green handle (true) leads to the path taken when the condition matches. The red handle (false) leads to the alternative path.
58
-
59
- You can chain conditions. Connect the output of one condition to the input of another to create complex decision trees.
@@ -1,93 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- import { Screenshot } from '../../../components/Screenshot'
6
-
7
- # Asset Library
8
-
9
- The Asset Library stores the files your content references: images, video, documents, and HTML.
10
-
11
- <Screenshot
12
- route="/{orgSlug}/{projectId}/assets"
13
- alt="The asset library on the Picked dashboard"
14
- />
15
-
16
- ## Upload and manage assets
17
-
18
- The Asset Library is a project-level store. Upload a file, then reference it from any Content Entry in the project.
19
-
20
- - **Size limit:** 50 MB per file.
21
- - **Allowed types:** images (PNG, JPEG, WebP, AVIF, GIF, SVG), video (MP4, WebM), common document formats, and HTML (`text/html`).
22
-
23
- Uploads outside the allowed types or over the size limit are rejected at upload time.
24
-
25
- ## Reference an asset from a field
26
-
27
- Two field types point at library items:
28
-
29
- - An **Asset** field references an image, video, or document.
30
- - An **HTML asset** field references an uploaded `.html` file.
31
-
32
- Add the field to a [layout](/content/layouts), then pick a library item when filling in the [Content Entry](/content/content-entries).
33
-
34
- ## Pick an asset
35
-
36
- Every Asset field opens the same picker: click **Choose file** (or **Replace** on a field that already has a value) to open a modal with two tabs, **Library** (browse existing assets) and **Upload** (add a new file).
37
-
38
- <Screenshot
39
- route="/{orgSlug}/{projectId}/design-systems/new"
40
- wait='button:has-text("Upload file")'
41
- click='button:has-text("Upload file")'
42
- selector="[role=dialog]"
43
- alt="The asset picker modal on the Picked dashboard, showing the Library tab with its search box, type filter, and Sort by menu"
44
- renderWidth={1072}
45
- renderHeight={790}
46
- />
47
-
48
- ### Search, filter, and sort
49
-
50
- The Library tab has three controls for narrowing a large asset list, all applied on the server across the whole library, not just the assets already loaded:
51
-
52
- - **Search:** filters by file name as you type.
53
- - **Type filter:** narrows to a media-type bucket (All types, Images, Video, Audio, Documents, or Archives).
54
- - **Sort by:** orders by Name or Date uploaded, each ascending or descending.
55
-
56
- :::note
57
- Results are paginated. Use **Load more** at the bottom of the list to fetch the next page.
58
- :::
59
-
60
- ### Select one or several assets
61
-
62
- The picker adapts to how many assets the field accepts:
63
-
64
- - A field that holds a single asset (a layout's Asset field, or a design system's guidance file) shows a **radio** indicator next to each row. Picking a new asset replaces the current one.
65
- - A surface that accepts several assets at once (for example, a workbench's Files tab) shows a **checkbox** indicator and a running selection count in the detail panel.
66
-
67
- The detail panel on the right shows the selected asset's kind, dimensions, size, and upload date.
68
-
69
- ### Open an asset in a new tab
70
-
71
- Each row, and the detail panel for the currently selected asset, has an **Open in new tab** control. It links to the asset's full detail page without losing your current selection in the picker.
72
-
73
- :::tip
74
- Use this to double-check an asset (its full-size preview, every uploaded version) before committing to it.
75
- :::
76
-
77
- ## HTML assets
78
-
79
- Upload a `.html` file and reference it from an **HTML asset** field. On upload, Picked runs an advisory scan that guides you but never blocks the upload. It surfaces performance, SEO, and accessibility findings so you can improve the file before publishing:
80
-
81
- - **File size:** a warning at 100 KB and a stronger one at 250 KB.
82
- - **Inline images:** a note when inline base64 image data adds roughly 50 KB or more.
83
- - **Image dimensions:** images missing an explicit width or height, which risk layout shift.
84
- - **Lazy loading:** images without `loading="lazy"`.
85
- - **Link safety:** external links with `target="_blank"` but no `rel="noopener"`.
86
- - **Link SEO:** external links without `rel="nofollow"`.
87
- - **Accessibility:** an axe-core pass covering alt text, heading order, contrast, and more.
88
-
89
- Every finding is advisory. You can always upload the file as is.
90
-
91
- ## How assets are served
92
-
93
- Assets are served from a sandboxed storage origin, separate from your app's trusted origin. Serving HTML from its own origin means an uploaded document executes in isolation and cannot reach the page that embeds it. When an [Experience Content](/delivery-api/experience-content) response includes an HTML asset, its content is inlined into the response, so the SDK renders it without a second storage fetch.
@@ -1,30 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- import { Screenshot } from '../../../components/Screenshot'
6
-
7
- # Content Entries
8
-
9
- A Content Entry is an instance of a layout filled with real data. A Page renders one entry; a Flow Step can render one too.
10
-
11
- <Screenshot
12
- route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/content"
13
- alt="The content entries list on the Picked dashboard"
14
- />
15
-
16
- ## What a content entry is
17
-
18
- A Content Entry is an instance of a layout's schema. The [layout](/content/layouts) defines the fields; the entry holds the actual values. One layout can back many entries, each with its own data.
19
-
20
- ## How entries bind to pages and steps
21
-
22
- A [Page](/content/pages) has a single Step, and that Step links to its entry through the layout content link. A Flow [Step](/steps) backed by a Step Layout binds an entry the same way. When the SDK renders the Page or Step, it resolves the linked entry and hands its data to your component.
23
-
24
- ## Edit entry data
25
-
26
- The entry editor renders a form driven by the layout schema: one input per field, in the order the schema defines. Repeatable fields appear as sortable lists you can add to and reorder. Group fields nest their inputs under a single heading.
27
-
28
- ## Validation
29
-
30
- Invalid data surfaces as per-field errors using a JSON-path style that points at the exact location in the entry, for example `sections[0].data.title`. Fix every error before publishing: the published surface only serves valid content.