API and automation
Everything the UI does, it does through a public HTTP API. You can drive the same API yourself.
Authenticating
Two ways, depending on who is calling.
Personal access tokens
For scripts, CI and tools. Mint one from your account settings and send it as a bearer token:
curl -H "Authorization: Bearer $PS_TOKEN" \
https://<your-platformsmith-host>/api/v1/workspaces
A personal access token acts as you, with your permissions. It is shown once when created and cannot be retrieved afterwards.
Treat it as a password:
- Give each tool its own token, so one can be revoked without breaking the others.
- Never commit one, and never put one in a URL — it ends up in logs and link previews.
- Delete tokens you have stopped using.
Session login
For interactive use, POST /api/v1/auth/login returns a JWT you send the same way. JWTs expire:
a long-running script should handle a 401 by logging in again rather than assuming something broke.
The scope walk
Paths follow the object model, outermost to innermost:
workspace → project → environment → { agent definitions, playbooks, runtimes, sessions }
Most collection routes hang off a workspace (/api/v1/workspaces/{uuid}/projects), and most
single-object routes address the object directly by UUID
(/api/v1/projects/{uuid}). Where both shapes exist, they do the same thing.
Knowing when a runtime is ready
This is the single most common cause of a script that waits forever, and it is worth reading before you write one.
Two endpoints return two different shapes, and they answer different questions:
| Endpoint | Returns | Carries |
|---|---|---|
GET /api/v1/workspaces/{uuid}/runtimes | runtime instances — the live containers | instance_uuid, connected, ready, last_seen, setup_at |
GET /api/v1/runtimes?workspace_uuid= | the parent runtimes | status (active / inactive) |
status fieldNot "sometimes absent" — it is never there. A script that calls the workspace-scoped endpoint and
then tests status gets undefined for every runtime, and waits forever on containers that came
up minutes ago.
On the instance, connected and ready are different axes — not synonyms:
connected— is it alive right now? The live heartbeat from your controller. This is the one to poll when you are waiting for a container to come up.ready— did it finish provisioning at some point? True long after a container has stopped.
Conflating them will tell you a hundred sandboxes are running when three are. If you want "alive
now", read connected.
And if you are reading the parent runtime's status instead: it lags, so it will not tell you a
container is up. Read the instance.
Other rules worth knowing before your first script
- Secret values are never returned. You can create, replace and reference a secret; you cannot read one back. Not through the API, not through the MCP server.
- Everything is tenant-scoped. Every response is filtered to your organization. There is no cross-organization read, with any credential.
- Your permissions apply. A token cannot do what its owner cannot do. → Security and tenancy
What else can drive the platform
| Surface | Use it for |
|---|---|
| The HTTP API | Anything. The full surface |
| The MCP control plane | Letting an AI assistant operate PlatformSmith for you |
| Streaming (SSE and WebSocket) | Following a session or a launch live instead of polling |
| Workspace provisioning recipe | Standing up a whole workspace from scratch, in order |