---
title: "Provision Workspace"
method: POST
path: "/api/v1/internal/workspaces/provision"
tags: ["internal", "workspaces"]
---

# Provision Workspace

`POST /api/v1/internal/workspaces/provision`

Provision a new workspace end-to-end with a Neon sandbox + counties.

Replaces the legacy bare-create `POST /`. A workspace with no loaded
counties has zero geographic query access, so provisioning is the only
sanctioned create path. Seeds the `workspace_counties` rows as `loading`
and fires the `stand_up_workspace` Dagster job. Returns once the rows
are persisted (5-15s for Neon create); county data loads asynchronously
thereafter.

## Request body

- AdminWorkspaceProvisionRequest — Request body for provisioning a new workspace end-to-end. Wraps `AdminWorkspaceService.provision_workspace_with_counties`: creates the Neon sandbox and seeds `workspace_counties` rows. At least one county is mandatory — a workspace with no loaded counties has zero geographic query access. Rejects unknown fields with 422. `counties` non-emptiness and in-list duplicates are validated in the service (400) rather than here, so the same guard covers the script caller (`scripts/provision_prod_admin_workspace.py`) and the error is a 400, not a 422, matching the rest of the provisioning contract.
  - `name` string, required
  - `counties` WorkspaceCountySelection[], required
    - `state_fips` string, required
    - `county_fips` string, required
  - `initial_credits` integer
  - `region_id` string, nullable
  - `icp_category_id` string, uuid, nullable — Optional ICP category to assign at creation. Omit or pass null to leave the workspace unassigned.

## Response `200`

Successful Response

- AdminWorkspaceDetailResponse — Full workspace detail response for admin view.
  - `id` string, uuid, required
  - `name` string, required
  - `budget_authority` 'credits' | 'discovery_allowance', required
  - `avatar_color` string, nullable, required
  - `available_enrichment_credits` integer, required
  - `used_enrichment_credits` integer, required
  - `remaining_credits` integer, required
  - `is_suspended` boolean, required
  - `is_internal` boolean, required
  - `icp_category_id` string, uuid, nullable, required
  - `member_count` integer, required
  - `project_count` integer, required
  - `members` AdminWorkspaceMemberItem[], required
    - `id` string, uuid, required
    - `email` string, required
    - `display_name` string, nullable, required
    - `workspace_role` string, nullable, required
    - `is_internal` boolean, required
    - `is_suspended` boolean, required
    - `created_at` string, date-time, nullable, required
    - `used_enrichment_credits` integer, required
    - `last_active_at` string, date-time, nullable, required
  - `created_at` string, date-time, nullable, required
  - `updated_at` string, date-time, nullable, required

## Other responses

- `422` — Validation Error

## Changes

> 15 revisions in range; 12 could not be searched.

- **2026-08-05** `bd2347b6f591` — 2 info
  - added the new optional request property `icp_category_id`
  - added the required property `icp_category_id` to the response with the `200` status

[Change history](https://skmtc.dev/maia-analytics/apis/maia-api/changes/api/v1/internal/workspaces/provision/post.md)

---

[API](https://skmtc.dev/maia-analytics/apis/maia-api.md) · [All operations](https://skmtc.dev/maia-analytics/apis/maia-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/maia-analytics/maia-api/revisions/0c94a4b5a00e/schema)
