API Reference
OIDC
Platform

Users

AdminUpdated Sep 11, 2026

Users

Create, read, update, and lifecycle-manage the people in your instance, plus their email addresses, linked identities, and OAuth consent grants.

The User object never includes private_metadata on a read. Timestamps are epoch ms.

{
  "object": "user",
  "id": "user_2a…",
  "username": null,
  "first_name": "Ada",
  "last_name": "Lovelace",
  "image_url": null,
  "public_metadata": { "plan": "pro" },
  "mfa_enabled": true,
  "banned": false,
  "locked": false,
  "last_sign_in_at": 1757600000000,
  "created_at": 1757000000000,
  "updated_at": 1757600000000
}

Endpoints

Method & path

Scope

Notes

GET /v1/users

users:read

List, cursor-paginated

GET /v1/users/:id

users:read

Never includes private_metadata

POST /v1/users

users:write

Create from email + optional password/name/metadata. Emits user.created. idempotent

PATCH /v1/users/:id

users:write

Update profile or metadata. idempotent

PUT /v1/users/:id/metadata

users:write

Replace the metadata bags wholesale. idempotent

DELETE /v1/users/:id

users:delete

Soft-delete; PII scrubbed after 30 days. idempotent

POST /v1/users/:id/ban

users:write

Ban and revoke every session. idempotent

POST /v1/users/:id/unban

users:write

Lift a ban (sessions are not restored). idempotent

POST /v1/users/:id/lock

users:write

Lock out sign-in for an optional duration (default 1 year). idempotent

POST /v1/users/:id/unlock

users:write

Clear a lockout. idempotent

POST /v1/users/:id/reset_mfa

users:write

Remove every second factor + recovery codes. idempotent

DELETE /v1/users/:id/mfa/:factorId

users:write

Remove one factor (last removal turns MFA off). idempotent

GET /v1/users/:id/sessions

users:read

The user's active sessions

POST /v1/users/:id/sessions/revoke

users:write

Revoke all sessions, bump sessions_version. idempotent

POST /v1/users/:id/email_addresses

users:write

Add an address (starts unverified). idempotent

POST /v1/users/:id/email_addresses/:eid/verify

users:write

Mark verified on the backend authority. idempotent

POST /v1/users/:id/email_addresses/:eid/primary

users:write

Make a verified address primary. idempotent

GET /v1/users/:id/identities

users:read

Base Atlas identity + linked providers. No tokens.

POST /v1/users/:id/identities

users:write

Merge a secondary user into this one. idempotent

DELETE /v1/users/:id/identities/:identityId

users:write

Unlink a provider into a new standalone user. idempotent

POST /v1/users/:id/external_accounts/connect

users:write

Backend-initiated OAuth link; returns an authorization_url

GET /v1/users/:id/oauth_access_tokens/:provider

oauth_tokens:read

Stored provider token, refreshed if stale

GET /v1/users/:id/grants

grants:read

OAuth clients the user authorized

DELETE /v1/users/:id/grants

grants:write

Revoke all consent grants + tokens. idempotent

DELETE /v1/grants/:id

grants:write

Revoke one consent grant. idempotent

Bulk import / export

Method & path

Scope

Notes

POST /v1/user_imports

jobs:write

Bulk-create users (dedupe by verified email). Argon2id hashes imported verbatim; plaintext is hashed; other formats rejected per-row. idempotent

POST /v1/user_exports

jobs:write

Produce a serialised export job. Never contains password hashes / tokens. idempotent

GET /v1/jobs · GET /v1/jobs/:id · GET /v1/jobs/:id/errors

jobs:read

Track jobs, counters, and per-row errors

Examples

# Create a user, idempotently
curl https://api.atlas.dev/v1/users \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: signup-ada-001" \
  -d '{"email_address":"ada@example.com","first_name":"Ada","email_verified":true}'

# Ban a user (revokes every session)
curl -X POST https://api.atlas.dev/v1/users/user_2a/ban \
  -H "Authorization: Bearer sk_live_xxx"
// @atlas/backend
const user = await atlas.users.create({ email_address: 'ada@example.com', first_name: 'Ada' });
await atlas.users.update(user.id, { public_metadata: { plan: 'pro' } });
await atlas.users.lock(user.id, { duration_in_seconds: 3600 });

// Merge a duplicate account into this one
const { collisions } = await atlas.users.linkIdentity(user.id, { secondary_user_id: 'user_dupe' });

// Read a stored Google token (auto-refreshed)
const { token } = await atlas.users.getOAuthAccessToken(user.id, 'google');
# atlas-backend (Python)
user = atlas.users.create({"email_address": "ada@example.com", "first_name": "Ada"})
for u in paginate(atlas.users.list):
    print(u["id"])
Was this page helpful?