Docs
Search docs

Preview what deleting a team removes

GET/api/teams/{team_id}/delete-preview

getTeamDeletePreview

Requires workspace admin or owner, the same decision as `DELETE /api/teams/{team_id}`. Counts the team's live tickets (open and closed), cycles, labels, memberships and repository grants, and lists up to 20 open tickets newest first with `more_open_tickets` counting the rest.

Requires authentication using a bearer token or a session cookie — see tokens and scopes.

curl

curl -X GET 'https://neosource.dev/api/teams/TEAM_ID/delete-preview' \
  -H 'Authorization: Bearer $NEOSOURCE_TOKEN'

fetch

fetch("https://neosource.dev/api/teams/TEAM_ID/delete-preview", {
  method: "GET",
  headers: {
    Authorization: "Bearer $NEOSOURCE_TOKEN",
  },
});

Path parameters

team_idrequired

string

Responses

200What the delete would remove

application/json

TeamDeletePreviewResponse

object

What `DELETE /api/teams/{team_id}` would remove, read before the caller confirms it. `tickets` counts live tickets only. Soft-deleted ones are deleted too but were already gone from every view, so they are not counted here. `repo_grants` counts every grant the team holds, including grants on repositories the caller may not read. It is a fact about the team, the delete removes all of them, and no repository is named.

cyclesrequired

integerint64

keyrequired

string

labelsrequired

integerint64

membersrequired

integerint64

Team memberships removed. The accounts themselves stay.

more_open_ticketsrequired

integerint64

Open tickets beyond `open_tickets`: `tickets.open - open_tickets.len()`.

open_ticketsrequired

array

Up to 20 not-closed tickets (every non-terminal status), newest first.

items

TeamDeletePreviewTicket

object

One open ticket the delete would take, as the confirm dialog lists it.

assigneesrequired
issue_idrequired

string

numberrequired

integerint32

The `N` in `KEY-N`.

statusrequired
IssueStatus
titlerequired

string

repo_grantsrequired

integerint64

Repository grants removed with the team.

team_idrequired

string

ticketsrequired

TeamIssueCounts

object

The team board's exact `(status, blocked)` cross-tab, plus the scalars derived from it. The cells are the one source; the scalars are arithmetic over them (see [`TeamIssueCounts::from`]), so a scalar cannot drift from the cross-tab. Clients that need the digest's groups compute them from `cells` — "blocked wins one group per row" is a UI rule, not a fact about the data.

blocked_openrequired

integerint64

Open AND blocked — the digest's blocked group.

cellsrequired
closedrequired

integerint64

Terminal issues.

openrequired

integerint64

Non-terminal issues (`IssueStatus::is_terminal()` is false).

totalrequired

integerint64

403Forbidden — one of: forbidden, needs_scope

application/json

one of
  • ErrorForbidden
  • NeedsScopeError

    object

    `403` body returned when a classic OAuth token is asked for something its granted scopes do not cover — an explicit private listing without `repo`, or the one-click GitHub mirror without `admin:public_key`. `scope` names the missing grant so the client can say exactly what the token lacks. There is no elevation route to widen it any more (a re-link goes through the GitHub App, whose tokens carry no scopes), so the client's answer is to say so, never to start a handshake.

    errorrequired

    string

    Always `needs_scope` — this body exists to carry the extra fields that kind needs.

    "needs_scope"

    scoperequired

    string

    The provider scope to request via elevation (e.g. `"repo"`).

Standard errors

Bodies documented once for the whole API — see standard errors.

  • 400Bad Request — one of: invalid_input
  • 401Authentication required
  • 404Not Found — one of: not_found
  • 429Rate limited — retry after the `Retry-After` header
  • 500Internal server error
  • 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
  • 504Gateway timeout — the request exceeded the server's handling budget

Schemas

Referenced above. Listed here rather than expanded inline, so the same definition is not repeated at every level.

IssueAssigneeResponse

object

One assignee, resolved to something renderable. This used to be a bare `account_id` string; a UUID is not a UI, and every consumer would otherwise have to fan out to the account store itself.

account_idrequired

string

display_namerequired

string

handlerequired

string

kindrequired

AccountKind

string

Rust mirror of the Pg `account_kind` enum (`accounts.kind`). `Ghost` rows are imported-author placeholders (GitHub metadata import, plans/github-metadata-import.md §6): `handle = gh-<github-id>`, `personal_workspace_id` NULL, no password, no sessions. They must never flow through `get_account*` (`AccountRow::into_record` CorruptData-errors on the NULL workspace) — author rendering goes through `PgGithubImportStore::authors_projection`, and claim-by-proof later promotes or merges them.

"human""bot""service""runner""ghost"

IssueStatus

string

"backlog""todo""in_progress""in_review""done""cancelled""duplicate"

TeamIssueCountCell

object

One `(status, blocked)` cell of [`TeamIssueCounts`]. Only non-empty cells are returned.

blockedrequired

boolean

countrequired

integerint64

statusrequired

IssueStatus

string

"backlog""todo""in_progress""in_review""done""cancelled""duplicate"