Sign in

End-users

Each generation is grouped under the email of YOUR end-user (the real person inside your product who triggered it). Use these endpoints to list, block, and delete them.

Semantics

  • Block — instant stop on new generationsSets `blockedAt` to now. Future POST /v1/generations with this email returns 403 `forbidden`. Pending generations (queued / processing) continue to terminal status — block does **not** cancel in-flight work.
  • Unblock — re-enableClears the `blockedAt` flag. Generations are accepted again. Idempotent.
  • Delete — cascade removalRemoves the end-user record, every `requests` row for that email, and every stored image. **Pre-condition:** no pending generations. If any are queued/processing, the response is **409 `conflict`** — block first, wait for them to finish, then retry. We do NOT auto-cancel queued work because it is already paid for and partially executed.

GET /v1/end-users

List end-users (paginated).

Query params: `page`, `pageSize` (max 100), optional `blocked=true|false` to filter only blocked or only active, and optional `email` for case-insensitive substring match (max 254 chars). Each item carries activity counters and a `blockedAt` ISO timestamp (or `null` when active).

bash
curl 'https://api.xmode.ai/v1/end-users?pageSize=20' \
  -H "Authorization: Bearer xm_live_<your-key>"

# 200 OK
{
  "items": [
    {
      "email": "alice@your-product.com",
      "createdAt": "2026-04-15T08:12:00.000Z",
      "lastActiveAt": "2026-05-06T11:24:31.018Z",
      "totalRequests": 142,
      "totalXTokensSpent": 1420,
      "blockedAt": null
    }
  ],
  "page": 1,
  "pageSize": 20,
  "hasMore": false
}

POST /v1/end-users/{email}/block

Block an end-user.

Idempotent — calling on an already-blocked end-user updates `blockedAt` to now.

bash
curl -X POST 'https://api.xmode.ai/v1/end-users/alice%40your-product.com/block' \
  -H "Authorization: Bearer xm_live_<your-key>"

# 200 OK
{ "email": "alice@your-product.com", "blockedAt": "2026-05-06T11:24:31.018Z" }

POST /v1/end-users/{email}/unblock

Unblock an end-user.

Clears `blockedAt`. Idempotent.

bash
curl -X POST 'https://api.xmode.ai/v1/end-users/alice%40your-product.com/unblock' \
  -H "Authorization: Bearer xm_live_<your-key>"

# 200 OK
{ "email": "alice@your-product.com", "blockedAt": null }

DELETE /v1/end-users/{email}

Cascade delete (record + requests + stored images).

Returns 409 `conflict` if the end-user has any `queued` or `processing` generation. Otherwise removes everything we have for them and returns counts. R2 objects are deleted best-effort (lifecycle policies reap any stragglers).

bash
curl -X DELETE 'https://api.xmode.ai/v1/end-users/alice%40your-product.com' \
  -H "Authorization: Bearer xm_live_<your-key>"

# 200 OK
{
  "email": "alice@your-product.com",
  "deleted": true,
  "removedRequests": 142,
  "removedObjects": 167
}

# 409 Conflict (when there are pending generations)
{
  "error": {
    "code": "conflict",
    "message": "End-user has 3 active generation(s). Block first, wait for completion, then retry."
  }
}