Platform guides
03 · Service activation

Control which services a workspace runs.

Each service (Auth, Mail, Waitlist, Social, Trawl) is activated per workspace. New workspaces start with every service enabled; disable the ones you don't use. Endpoints of a disabled service return 403 SERVICE_NOT_ENABLED before any data leaks.


1

Why activation is per-workspace

  • Scoping — each of your workspaces (production, dev, per-client) runs only the services it actually needs.
  • Defence in depth — a misconfigured key shouldn't accidentally hit a service the workspace never wanted. The SERVICE_NOT_ENABLED check runs before any service-specific logic.

Today a new workspace is created with all five services enabled, so the console shows every product immediately — disabling is how you narrow the surface.


2

Enable a service

From the console (Workspace → Services, then Enable / Disable on the service row) or API:

POST /v1/workspaces/:slug/services/:service
# Enable (or re-enable) Mail
curl -X POST https://api.platform-auth.productcraft.co/v1/workspaces/acme/services/mail \
  -H 'authorization: Bearer <token-or-pak>' \
  -H 'content-type: application/json' \
  -d '{}'

# → 201, the full service state row:
{
  "workspace_id": "<workspace-uuid>",
  "service":      "mail",
  "enabled":      true,
  "enabled_at":   "2026-07-28T14:20:46.083Z",
  "enabled_by":   "<account-uuid>",
  "disabled_at":  null,
  "disabled_by":  null,
  "settings":     {}
}

Requires the workspace.service.enable permission. Valid service names are auth, mail, waitlist, social, trawl — anything else is a 400 SERVICE_UNKNOWN.


3

Per-service settings

Each activation row carries a free-form settings JSON blob whose shape is up to the service. Update it via PATCH /v1/workspaces/:slug/services/:service/settings — the request body is the settings object itself (no wrapper) and replaces the blob entirely:

PATCH /v1/workspaces/:slug/services/:service/settings
curl -X PATCH https://api.platform-auth.productcraft.co/v1/workspaces/acme/services/mail/settings \
  -H 'authorization: Bearer <token-or-pak>' \
  -H 'content-type: application/json' \
  -d '{ "default_sender": "noreply@acme.com" }'

# → 200, the updated service state row (settings included)

Requires workspace.service.enable. Patching a service that was never activated on the workspace returns 404 SERVICE_NOT_ACTIVATED.


4

Disable

DELETE /v1/workspaces/:slug/services/:service
curl -X DELETE https://api.platform-auth.productcraft.co/v1/workspaces/acme/services/mail \
  -H 'authorization: Bearer <token-or-pak>'
# → 204. Disabling a service that isn't enabled → 409 SERVICE_NOT_ENABLED.

Requires workspace.service.disable. Disable doesn't delete data — domains, templates, messages, settings are all preserved. Subsequent calls to the service's endpoints return 403 SERVICE_NOT_ENABLED. Re-enabling restores access (allow up to a minute for downstream permission caches to refresh). For permanent removal, delete the workspace (Chapter 1).


5

List active services

GET /v1/workspaces/:slug/services
curl https://api.platform-auth.productcraft.co/v1/workspaces/acme/services \
  -H 'authorization: Bearer <token-or-pak>'
{
  "data": [
    { "workspace_id": "...", "service": "auth",     "enabled": true,
      "enabled_at": "...", "enabled_by": "...",
      "disabled_at": null, "disabled_by": null, "settings": {} },
    { "workspace_id": "...", "service": "mail",     "enabled": true,  ... },
    { "workspace_id": "...", "service": "social",   "enabled": true,  ... },
    { "workspace_id": "...", "service": "trawl",    "enabled": true,  ... },
    { "workspace_id": "...", "service": "waitlist", "enabled": false,
      "disabled_at": "...", "disabled_by": "...", ... }
  ]
}

Requires workspace.service.read. A disabled service keeps its row with enabled: false and disabled_at set.


6

The SERVICE_NOT_ENABLED guard in practice

Useful for SDKs and customer support — what error to expect when a service hasn't been turned on.

Workspace-scoped endpoints on a service check activation before anything else. With the service disabled you get:

HTTP/1.1 403 Forbidden
{
  "statusCode": 403,
  "message":    "mail is not enabled on this workspace",
  "code":       "SERVICE_NOT_ENABLED"
}

This 403 isn't a permission failure. Your role and policies are fine — activation is a structural prerequisite, not an authz outcome. Re-enable the service and the same call succeeds.