{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/zvid-io/json-schema/zvid-io-user-profile-schema.json",
  "title": "UserProfile",
  "x-generated": "2026-10-31",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/zvid-io-openapi.yaml#/components/schemas/UserProfile",
  "type": "object",
  "properties": {
    "user": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "firstName": {
          "type": "string"
        },
        "lastName": {
          "type": "string"
        },
        "emailVerified": {
          "type": "boolean"
        },
        "profileCompleted": {
          "type": "boolean"
        },
        "pendingRedirect": {
          "type": [
            "string",
            "null"
          ]
        },
        "isAdmin": {
          "type": "boolean"
        },
        "createdAt": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "email",
        "emailVerified",
        "createdAt"
      ],
      "additionalProperties": false
    },
    "credits": {
      "$ref": "#/$defs/CreditBalance"
    },
    "plan": {
      "type": "object",
      "description": "Current plan and enforced account allowances. A null count means unlimited; absent values are unavailable.",
      "properties": {
        "name": {
          "type": "string"
        },
        "isPaid": {
          "type": "boolean"
        },
        "uploadStorageBytes": {
          "type": [
            "integer",
            "null"
          ]
        },
        "maxProjects": {
          "type": [
            "integer",
            "null"
          ]
        },
        "maxDesigns": {
          "type": [
            "integer",
            "null"
          ]
        },
        "maxApiKeys": {
          "type": [
            "integer",
            "null"
          ]
        },
        "maxTemplates": {
          "type": [
            "integer",
            "null"
          ]
        },
        "outputRetentionDays": {
          "type": [
            "integer",
            "null"
          ]
        },
        "outputRetentionMonths": {
          "type": [
            "integer",
            "null"
          ]
        },
        "apiRequestsLimitPerHour": {
          "type": [
            "integer",
            "null"
          ]
        },
        "apiRequestsLimitPerMinute": {
          "type": [
            "integer",
            "null"
          ]
        }
      },
      "additionalProperties": true
    }
  },
  "required": [
    "user",
    "credits"
  ],
  "additionalProperties": false,
  "$defs": {
    "CreditBalance": {
      "type": "object",
      "properties": {
        "balance": {
          "type": "integer",
          "description": "Total available credits from subscription and add-on pools"
        },
        "subscriptionCredits": {
          "type": "integer",
          "description": "Credits remaining in the current subscription period"
        },
        "addonCredits": {
          "type": "object",
          "description": "Add-on credit pool and historical add-on totals",
          "properties": {
            "balance": {
              "type": "integer",
              "description": "Available add-on credits"
            },
            "totalEarned": {
              "type": "integer",
              "description": "Total add-on credits earned over all time"
            },
            "totalSpent": {
              "type": "integer",
              "description": "Total add-on credits spent over all time"
            }
          },
          "required": [
            "balance",
            "totalEarned",
            "totalSpent"
          ],
          "additionalProperties": false
        }
      },
      "required": [
        "balance",
        "subscriptionCredits",
        "addonCredits"
      ],
      "additionalProperties": false
    }
  }
}