Sandbox (nex_test_ keys)
Requests authenticated with a nex_test_ API key use the same production database as live traffic, but only see and mutate rows marked is_sandbox = true. Live keys (nex_live_), personal access tokens (nex_pat_), and normal browser sessions only see rows where is_sandbox is false (legacy rows without the flag are treated as live).
For the full rationale and migration notes, see ADR 0003 in the repository (docs/decisions/0003-sandbox-environment.md).
Isolation rules
New rows created while handling a sandbox request are stored with
is_sandbox = true. Updates and deletes apply only within that partition, so test keys cannot modify production shift/staff/credential/payroll rows and production traffic cannot touch sandbox copies.
Tables in Phase 1 scope
Row-level isolation is enforced today on the highest-traffic transactional surfaces, including:- Shifts (related assignments and shift-linked flows follow shift visibility)
- Staff
- Credentials
- Payroll runs
- API key usage events (each request log carries
is_sandbox)
is_sandbox everywhere. If you call an endpoint outside this scope, assume isolation is not guaranteed until covered by the same pattern.
Side effects
Sandbox requests do not deliver real user notifications (push, SMS, email); attempts are skipped and logged. Outbound platform webhooks are not emitted for sandbox-key traffic.Usage analytics and outcomes
AllGET /api/api-usage/* aggregates (summary, timeseries, by-agent, by-tool, by-key, outcomes) include production traffic only: rows with is_sandbox = true are excluded so outcome counts align with billing-oriented views.
Retention (TTL) and reset
Two independent mechanisms keep the sandbox tidy:- Retention purge (global safety net). Sandbox rows older than 30 days are deleted by a daily background job. Purge order favors dependents (e.g. shifts first where cascading applies), then staff, credentials, payroll runs, and sandbox usage-event rows.
- On-demand reset (immediate, facility-scoped).
POST /api/sandbox/resetclears a single facility’s sandbox rows and re-seeds a small synthetic dataset (5 workers, 10 open shifts) so you can start from a predictable slate.
Reset is a dashboard/session operation restricted to NexSpace 365 administrators. It cannot be called with an API key (including a
nex_test_ key) — this prevents a low-scope token from wiping data. Sign in and call it with your session, use nexspace fixtures sandbox-reset, or trigger it from the developer settings UI.Related
- Authentication — key prefixes and scopes
- Usage analytics — OpenAPI for
/api/api-usage/* - CLI fixtures —
nexspace fixtures sandbox-reset

