Workspace Environments
Throttle isolates production from every sandbox-provider environment inside the same workspace. Each workspace has one immutable production environment and can have multiple non-production environments such as test, UAT, and staging.
Environment-scoped keys
API keys are minted for a workspace environment. The raw key includes the environment slug, and every request is scoped to the key's environment end-to-end:
sk_<environment-slug>_*— secret key for server-side requests.pk_<environment-slug>_*— publishable key for browser/frontend code. Publishable keys may hold only stateless compute scopes such asshipping_quotes:writeandtax_calculations:write.
# API keys include the workspace environment slug.
# Production is immutable; non-production environments can be named for your flow.
THROTTLE_API_KEY=sk_uat_3e2e04df... # non-production secret key
THROTTLE_PUBLISHABLE_KEY=pk_uat_290b29b1... # non-production publishable key
# Production:
THROTTLE_API_KEY=sk_production_fbc6cab6...
THROTTLE_PUBLISHABLE_KEY=pk_production_06646787...environmentId. A UAT cart never becomes a production order, and a production webhook endpoint never receives UAT events.Dashboard environment selector
The dashboard topbar selector chooses the active workspace environment for reads and setup writes. Production workspaces can switch between production and any active non-production environment. Workspaces that have not completed go-live can work in non-production environments until production is available. Create and archive custom environments from Workspace Settings → Environments.
// Dashboard and Clerk-authenticated setup calls select an environment explicitly.
// The selected id comes from GET /api/v1/workspaces/{workspaceId}/environments.
await fetch('https://api.usethrottle.dev/api/v1/api-keys', {
method: 'POST',
headers: {
Authorization: 'Bearer <dashboard-session>',
'X-Throttle-Application-Id': '<applicationId>',
'X-Throttle-Environment-Id': '<workspace-environment-uuid>',
'content-type': 'application/json',
},
body: JSON.stringify({
name: 'UAT backend',
scopes: ['orders:read', 'payments:write'],
}),
});Manage environments
Every workspace starts with one immutable production environment. Create additional environments for UAT, staging, or QA; each custom environment is non-production and routes to sandbox-provider credentials. Production cannot be created, archived, or deleted. Archiving a custom environment removes it from normal selectors and prevents new work in that environment; historical rows keep their environment id for audit and reporting.
# List active environments
curl https://api.usethrottle.dev/api/v1/workspaces/<workspaceId>/environments \
-H "Authorization: Bearer <dashboard-session>"
# Include archived environments for settings/audit screens
curl "https://api.usethrottle.dev/api/v1/workspaces/<workspaceId>/environments?includeArchived=true" \
-H "Authorization: Bearer <dashboard-session>"
# Create a non-production sandbox-provider environment
curl -X POST https://api.usethrottle.dev/api/v1/workspaces/<workspaceId>/environments \
-H "Authorization: Bearer <dashboard-session>" \
-H "content-type: application/json" \
-d '{ "slug": "uat", "name": "UAT" }'
# Archive a custom non-production environment
curl -X DELETE https://api.usethrottle.dev/api/v1/workspaces/<workspaceId>/environments/8a5f2d1e-3d2a-4d24-93a1-fd3f9e1f37f0 \
-H "Authorization: Bearer <dashboard-session>"API keys are environment-scoped
GET, POST, and DELETE /api/v1/api-keys act only on the request's selected environment. Create separate keys for production, UAT, staging, or any other non-production environment you run.
environment_mismatch. Use a key for the correct environment, or select the matching X-Throttle-Environment-Id for dashboard-session setup calls.Payment provider environments
Throttle uses the workspace environment to choose the provider environment. Production routes to production processors; non-production environments route to sandbox-provider wiring such as the Card Simulator or sandbox payment processor.
// Provider routing comes from the selected workspace environment:
//
// kind=production -> providerEnvironment=production
// kind=non_production -> providerEnvironment=sandbox
//
// Your code sends the environmentId (or uses an API key minted in that
// environment); the API resolves the payment provider wiring automatically.Webhook environment routing
Outbound webhook endpoints are scoped to a workspace environment. Events carryenvironmentId in the delivered envelope and are delivered only to endpoints in the same environment.
POST /api/v1/webhook-endpoints
{
"url": "https://shop.example.com/webhooks/throttle/uat",
"enabledEvents": ["order.created", "payment.captured"]
}
// Delivery envelope:
{
"id": "evt_...",
"type": "order.created",
"version": "1",
"createdAt": "2026-06-03T12:00:00.000Z",
"environmentId": "8a5f2d1e-3d2a-4d24-93a1-fd3f9e1f37f0",
"workspaceId": "ws_...",
"data": {}
}Cheat sheet
- Use non-production environment keys such as
sk_uat_*for development and UAT. - Use
environmentIdto choose dashboard-session setup scope; API keys already carry their environment. - Going live makes the immutable production environment usable for production payment paths without changing the structure of your integration code.