---
title: "Bulk User Action"
method: POST
path: "/api/v1/admin/users/bulk"
tags: ["admin"]
---

# Bulk User Action

`POST /api/v1/admin/users/bulk`

## Request

- Base URL: `https://api.peil.app` (the document declares no server; this is the origin it was published from)
- URL: `https://api.peil.app/api/v1/admin/users/bulk`
- Auth: OAuth 2 (password, token URL `/api/v1/auth/jwt/login`)

Apply one action to an explicit set of accounts, reporting every skip.

Sync session on purpose: `delete` reuses `purge_user` (ordered child-first
deletes + the Mollie-cancel backstop), which is sync — reimplementing it in
async would be a second, drifting copy of fragile FK-ordering logic. The
other three actions are trivial column writes.

Guardrails, all surfaced rather than silent:
  - the acting admin and any other admin are never touched (`is_admin`);
  - `revoke_grant` only ends a grant (`REVOCABLE_SOURCES`);
  - `ban`/`delete` refuse on a live paid subscription (`_is_paying`).

`ban` sets is_active=False (fastapi-users blocks login on it and the deck
drops the account from every count); `delete` is irreversible.

## Request body

- BulkUserAction
  - `user_ids` integer[], required
  - `action` string, required

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/peil/apis/peil-api.md) · [All operations](https://skmtc.dev/peil/apis/peil-api/llms.txt) · [OpenAPI document](https://skmtc.dev/peil/apis/peil-api/revisions/ee3ca1246dde?raw)
