Delete a project in one of two modes.
Detach (the default, no body or mode: detach): only the
grouping row is removed; every resource in the project moves to the
implicit Default project. Refused with 409
project_has_scoped_credentials while an API key, service account,
vault credential, webhook endpoint, member grant or pending invite is
scoped to the project, because detaching any of those would silently
widen it.
Purge (mode: purge with confirm equal to the project’s name):
available only on an ARCHIVED project, because an irreversible
teardown needs a state you can sit in and reverse first; a live
project is refused with the coded 409 project_not_archived. Archive
the project, confirm it is the one you mean, then purge. The project
is removed WITH its contents in one transaction. Agents
(with their tests), knowledge bases (with their documents), tools,
audio assets, scoped webhook endpoints and scoped vault credentials
are deleted; API keys and service accounts pinned to the project are
revoked; member grants and pending-invite scopes on the project are
cleared. Conversations, callers, batch calls, suite runs and memories
are operational records and survive exactly as on a detach: a
conversation keeps its frozen attribution, the others move to the
Default project. Refused with 409 while a phone number is attached
(release or move it first), while a member’s only project grant is
this one, or while a live invite carries only this project (clearing
either would widen that person to the whole workspace, the invite one
acceptance earlier). Preview either mode with
GET /v1/projects/{project_id}/teardown.
The 409 carries the blockers under error.details.blockers (kind,
typed id, name, and the blocks modes each refuses), their total
under error.details.blocker_count, and, for existing clients, the
same rows under error.details.credentials. The lists are capped at
50 rows; the counts are not, and the refusal is decided on the count.