{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/craaft-io/json-schema/craaft-io-user-schema.json",
  "title": "User",
  "x-generated": "2026-11-04",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/craaft-io-openapi.yml#/components/schemas/User",
  "type": "object",
  "required": [
    "id",
    "email",
    "name",
    "username",
    "avatarUrl",
    "hasPassword",
    "emailVerified",
    "newsletterSubscribed",
    "newsletterAvailable",
    "emailNotifications",
    "isSuperAdmin",
    "twoFactorEnabled"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "name": {
      "type": "string"
    },
    "username": {
      "type": "string"
    },
    "avatarUrl": {
      "type": "string",
      "description": "Empty when no upload; otherwise /api/v1/users/{id}/avatar"
    },
    "hasPassword": {
      "type": "boolean",
      "description": "False for OAuth-only users (no password set). The hash itself is never returned."
    },
    "emailVerified": {
      "type": "boolean",
      "description": "Whether the address has been confirmed. Currently a soft gate -\nevery endpoint still works for an unverified user - so treat it\nas a prompt to nudge, not as an authorization signal.\n"
    },
    "pendingEmail": {
      "type": "string",
      "format": "email",
      "description": "Present while an email change waits for confirmation. `email`\nstays the current address until the link sent to this one is\nopened.\n"
    },
    "twoFactorEnabled": {
      "type": "boolean",
      "description": "Whether the user has two-factor sign-in on. Managed from\nSettings → Security through session-only routes (`/me/2fa*`);\npersonal access tokens and MCP tokens are not affected by it.\n"
    },
    "newsletterSubscribed": {
      "type": "boolean"
    },
    "emailNotifications": {
      "type": "boolean",
      "description": "Whether card-activity emails are sent (mentions, assignments,\nand activity on followed cards that stays unread for a few\nminutes). Defaults to true. Account email such as password\nresets is always sent.\n"
    },
    "newsletterAvailable": {
      "type": "boolean",
      "description": "False when the newsletter feature isn't configured on the\ndeployment at all, which is different from being unsubscribed.\n"
    },
    "isSuperAdmin": {
      "type": "boolean",
      "description": "Whether the user can reach the `/admin` dashboard. Informational\nonly - the real gate is server-side, and the admin endpoints are\nsession-authenticated, so a token cannot use them.\n"
    },
    "csrfToken": {
      "type": "string",
      "description": "Present only for cookie/session callers, who need it to send\nmutations. Omitted for bearer-token callers, since CSRF does not\napply to a credential that isn't attached automatically.\n"
    }
  }
}