Skip to main content
A client portal (a space) is a page you share with one client: documents, forms, file uploads, action plans and a scheduler, behind an email gate. Your system can drive portals end to end: create one per client from a template you maintain in the dashboard, unlock sections as your process advances, and receive webhooks when the client fills a form, uploads a file or checks off a step.

Key Concepts

Authentication

Use a personal access token with the Portals capability (spaces), or a full-access token. A token limited to other capabilities receives 403 This token does not carry the 'spaces' capability.

Create a portal from a template

Build the template in the dashboard (Portals → ⋯ → Save as template), then list and instantiate it:
The response is the complete portal: every section and block with its id, so you can address them later. The copy is made in one transaction, and for a new client:
  • the previous client’s name in titles, descriptions and steps is replaced by customerCompanyName
  • the template’s client-specific branding (logo, colours, backdrop) is dropped and brandOverrides applied
  • action-plan progress starts at zero
Related: POST /space/{spaceId}/duplicate (same client, “(Copy)” suffix), POST /space/{spaceId}/save-as-template, POST /space/{spaceId}/section-from-template ({ "templateId", "index" }) and POST /space-section-template/from-section for reusable sections.

Control what the client sees

Portals are phase-driven: keep later requirements hidden or locked until the client gets there. Both levels take the same body.
Nothing has to be created or deleted per phase: a template carries every block, and your system flips visibility.

Invite the client

The personal link is https://cal.meetergo.com/spaces/{slug}?invite={inviteToken} (your own domain instead of cal.meetergo.com when a custom domain is configured). Opening it verifies the person’s email without a code; a link with requireEmailOtp asks anyone else for a one-time code.

Read the state of a portal

GET /space/{spaceId} returns sections, blocks and, on task blocks, every step:
assignee.side is them for the client and us for your team. completedAt and updatedAt are set by the server. Forms. GET /space/{spaceId}/form-status lists every form block in the portal with the submissions made inside this portal: whether the client handed it in, when, by whom, and the answers.
Files. GET /space/{spaceId}/uploads lists what the client uploaded to the upload zone (file name, type, size, who, when). GET /space/{spaceId}/uploads/{uploadId}/download returns a short-lived download URL. Files attached to a form answer arrive with that form’s submission instead.

Follow what the client does

Subscribe to the portal webhooks: space_viewed, space_invite_accepted, space_task_completed, space_task_reopened, space_file_uploaded. A form filled inside a portal arrives as form_submission with a space object naming the portal, block and viewer. Every portal event carries spaceId, the acting viewer and occurredAt, so it can be matched to your own records without a follow-up request.

Errors