Workspaces
A workspace is the boundary between one customer and another. Agents, tools, integrations, knowledge, calls, keys and webhooks belong to exactly one.GET /v1/workspaces lists the workspaces the credential can see (an API key sees exactly one). GET /v1/workspaces/{id} adds your_role and the agents in scope. PATCH /v1/workspaces/{id} renames (owner).
Organizations
An organization is the membership and billing umbrella over workspaces.GET /v1/organizations lists the caller’s workspace organizations. GET /v1/organizations/{organization_id} reads one (organizations:read); an id the credential cannot see answers 404 not_found, the same as an id that never existed. Membership and invitations are managed in the Sempera App.
Reseller-funded child organizations
POST /v1/organizations creates a child workspace under an existing reseller. It requires a signed-in reseller owner or admin, the session’s CSRF token and an allowed Sempera App origin. Workspace API keys do not carry reseller authority and are refused, even with organizations:write.
The JSON body contains parent_organization_id (the reseller partner id), name, owner_email, external_ref and optional support_responsibility (partner or sempera, default partner). Other fields are refused. The customer’s owner must already have an active Sempera account with a verified email and cannot be reseller staff. An established customer receives an ownership invitation through the existing invitation flow. The parent needs an approved entitlement and an available customer slot.
The child is always wholesale-funded: the reseller, not the child, is responsible for funding. Workspace creation and its parent link commit together. A new child returns 201. Reusing an external_ref under the same parent returns the existing child with 200, including when the parent’s customer slots are now full. Keep the reference stable after a lost response; use a different reference for a different customer. The App generates a reference for retries within the open form when none is supplied.
The response’s id is the partner customer id; workspace_id is the child’s workspace id. Manage existing children in the signed-in partner console: list and read customers, suspend or resume service, and read attributed usage for a date range. Those session-authenticated management operations are not part of this canonical API’s published route contract. Recorded amounts are not credit balances.
Each action checks the caller’s current reseller role and the parent-child relationship. Creating a child gives reseller staff no membership in it and no access to its calls or recordings.
Credit purchases, credit transfers and reseller price configuration are not enabled by this endpoint. The published credit offers remain catalogue-only. A usage allowance is not a purchased balance, and credits are not converted into minutes or cash. Credit settlement, reservation/consumption, reversals and price-floor enforcement must be implemented before these operations can be offered.
Doug text Assistant
These routes manage the workspace owner’s text channel from their signed-in Sempera App session. API keys, including owner and CI keys, cannot use them. Reads requireworkspaces:read; writes require workspaces:write, owner authority and CSRF proof. New work requires an active workspace and Assistant entitlement. The channel is default off and is available only on a deployment configured to deliver messages; these routes do not activate a provider.
The thread response contains
name, messages, has_more and next_before. Each message contains id, body, nullable answer, state and timestamp at. A page contains up to 50 messages, oldest first within that page. Pass before=<next_before> to fetch the next older page. The cursor must be a canonical UUID in this owner’s workspace thread; an unknown or foreign cursor returns no messages. An invalid cursor answers 400 validation_failed.
Linking codes expire after ten minutes and allow at most five verification attempts. Requests are throttled, and an already linked number must be unlinked before changing it. Settings expose only the mobile number’s last four digits. A disabled or unavailable channel does not imply a successful send.
Service version
A workspace pins the Sempera runtime release its new sessions start on, independent of any agent’s published version. Only releases installed on this deployment are listed; today that is one.GET /v1/org/service-versions(workspaces:read) answers{"versions": [...]}, each withid,nameandavailable.GET /v1/org/service-version(workspaces:read) answers the pin:{"version": "...", "applies_to": "new_sessions"}. A pin that cannot be read answers503 service_unavailable.PUT /v1/org/service-version(workspaces:write, owner only) with{"version": "...", "expected_version": "..."}changes it. A staleexpected_versionor a release that is not installed answers409 conflict; a paused workspace answers403 forbiddenon every route here.
Platform
GET /v1/platform (scope deploy:read, the CI and certification credential) reports the deployment’s build identity, its production posture and the current call-capacity snapshot. It never names a machine or a path.
API keys
GET /v1/api-keys, POST /v1/api-keys, GET /v1/api-keys/{id}, PATCH /v1/api-keys/{id}, DELETE /v1/api-keys/{id}. See Authentication and credentials for kinds, roles and scopes. Creating, renaming and revoking need the owner role and api_keys:write; from the App they also carry the session’s CSRF token. PATCH takes {"name": "..."} (1 to 120 characters) and changes only the label: the secret, scopes and role stay. A revoked key and a connection key (named mcp:, oauth: or rest:) answer 409 conflict, and a new name cannot start with one of those prefixes.