React SDK
@statisfy/portal-react — drop-in components (<OnboardingProject/>, <ProjectModule/>, <Comments/>) and headless hooks (useProject, useComments).REST API
The
/sdk/v1 endpoints the React SDK calls. Use them directly if you’re not on React.404 (existence is never leaked).
Authentication
Every call needs a portal session token (a short-lived JWT) as a bearer, plus your publishable key:<PortalAuthGate> owns the sign-in and refresh, and supplies <StatisfyProvider>. See Portal sign-in for the raw endpoints, and Publishable keys to create a key.
Visibility is enforced server-side. A real (non-preview) external viewer only receives fields, tasks, and comments that have been shared with the customer — see External sharing. An internal preview session sees everything.
What the customer can see and edit
- Fields marked Internal are removed from the response entirely.
- Tasks hidden from the portal are dropped from the task list.
- Comments that weren’t shared with the customer are filtered out; comments the customer posts are always shared.
- Writes are gated by
meta.can_editand each field’seditableflag.
REST API
Base path:/sdk/v1. All responses are JSON.
Error responses:
Resolve the onboarding project
onboarding_project__c_, which you then read with GET /projects/{id}.
onboarding_project__c_ is the Onboarding Project field on the Account — a system lookup field (pointing at a project) provisioned automatically — you never create it. The endpoint resolves it for the account the session token is scoped to, so each signed-in customer gets their own project with no id in your code.
To make it resolve, set that field on the account: open the account record and pick its project in Onboarding Project, or populate it in bulk via import, the API, or field automation. An account whose field is empty returns null here, and <OnboardingProject/> renders its empty state instead of falling back to another account’s project.
<OnboardingProject/> and <ProjectModule/> split on where the project id comes from. OnboardingProject reads this account field automatically — each signed-in customer sees their own project, no configuration beyond a configId. ProjectModule instead shows one project the portal’s author pins in Settings, the same project for every viewer; it’s visible only to the account that owns the pinned project, and every other signed-in account gets the empty state. Use OnboardingProject for the common per-account case; reach for ProjectModule only when every viewer should land on the same project.
In Portal Studio the field is surfaced in Settings → Components as the shared, Locked property “Onboarding project source” — read-only, because it is pinned platform-wide: re-pointing it would change onboarding for every portal at once. Configure the per-account value in Statisfy, not in the portal.
Read a project
display[key] ?? properties[key]; send only canonical properties back on writes. tasks is a flat, depth-first list — build the milestone → subtask tree client-side from parent_id, and never re-sort it.
Update a project or task
400 (not_editable / invalid_option / invalid_type).
Comments
GET returns customer-visible comments oldest-first:
POST takes { "value": "..." } and returns the created comment. Portal-posted comments are always shared with the customer. PATCH (author only) edits the text.
React SDK
Install and wrap your app in<StatisfyProvider> (see Portals overview); it supplies the base URL, token minting, and publishable key to every hook and component.
<OnboardingProject/>
The signed-in account’s own onboarding project — header, progress, milestone journey, editable task list, project comments, and a task-detail drawer, resolved from the account field described above. configId is required: it’s what puts the component in the portal’s config manifest (so its Settings card renders), and without it the component can never resolve — there’s no embed-mode fallback.
<ProjectModule/>
The pre-assembled view of one project pinned by the portal’s author — the same project for every viewer, not each account’s own. In a portal, configId names this instance’s config slot and the pinned project id comes from the portal’s Settings; outside a portal, pass projectId directly.
configId wins and projectId is ignored (with a console warning in development). The pinned project resolves against the signed-in account, so only users of the account that owns it can see it; everyone else gets the empty state. That’s intended: use OnboardingProject above for a per-account view.
<Comments/>
A standalone comment thread + composer — project-level, or task-level with a taskId. Used inside <ProjectModule/>, but also available on its own for custom layouts.
useProject(projectId?)
Headless data hook for custom layouts. Owns the config → project resolve, the milestone/subtask tree, and optimistic task/project writes with rollback.
<OnboardingProject configId="onboarding" />.