{
  "openapi": "3.1.0",
  "info": {
    "title": "Zeldoc Platform API",
    "description": "Read your organization's usage, plan cost and invoices from the Zeldoc\nplatform. This is the same data the dashboard shows. Guide:\nhttps://docs.zeldoc.ai/reporting-api\n\n## Authentication\n\nSend a **reporting token** as a bearer token:\n\n```\nAuthorization: Bearer zdt_...\n```\n\nAn organization admin creates reporting tokens in the dashboard\n(Organization → API tokens), where the organization id (`org_id`) every\npath takes is shown too. A token is read-only and belongs to one\norganization: it opens the endpoints listed here and nothing else, so it\ncannot create keys, invite users or mint further tokens.\n\n```bash\ncurl -s \"https://platform.zeldoc.ai/api/orgs/$ORG_ID/key-usage?month=2026-08\" \\\n  -H \"Authorization: Bearer $ZELDOC_TOKEN\" \\\n  -H \"User-Agent: my-company-usage-sync/1.0\"\n```\n\n## User-Agent\n\nSend an explicit, descriptive `User-Agent` header, for example\n`my-company-usage-sync/1.0`. The platform sits behind Cloudflare, which\nrejects the default user agent of some HTTP libraries (Python's `urllib`, for\none) with error 1010.\n\n## Money and tokens\n\n- Amounts are decimal **strings** (`\"12.3456\"`) so no precision is lost; parse\n  them as decimals, not floats.\n- `prompt_tokens` is the **whole** input, cache reads and writes included.\n  `cache_read_input_tokens` and `cache_creation_input_tokens` are subsets of\n  it, not additions. The four non-overlapping buckets that provider invoices\n  use are:\n\n  ```\n  uncached input = prompt_tokens - cache_read_input_tokens - cache_creation_input_tokens\n  cache write    = cache_creation_input_tokens\n  cache read     = cache_read_input_tokens\n  output         = completion_tokens\n  ```\n\n- Models Zeldoc hosts itself (`zeldoc_hosted: true`) are covered by the\n  subscription: zero spend, but their tokens and requests count.\n\n## Visibility\n\nWhat an organization sees of its money is agreed per customer. When usage,\nthe subscription or invoices are not shared with your organization, the\nmatching endpoints answer 403; contact Zeldoc.\n\n## Partners\n\nA partner runs an app on Zeldoc for other organizations, for example a hosted\nchat workspace with one key per customer. A partner's people create a\n**partner token** in the dashboard (Partner → API tokens); it opens\n`GET /api/partner/status` and nothing else. That one call lists every\norganization the partner serves and each key it runs there, compared with\nthe partner's recommended models, so a scheduled job can tell when a key\nneeds a model added.\n",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://platform.zeldoc.ai"
    }
  ],
  "paths": {
    "/api/orgs/{org_id}/invoices": {
      "get": {
        "tags": [
          "Invoices"
        ],
        "summary": "List invoices.",
        "description": "The invoices issued to the organization, newest first.",
        "operationId": "list_own_org_invoices",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "description": "Your organization id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invoices",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/InvoiceSummaryDTO"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Another organization's id, or invoices are not shared with your organization"
          },
          "409": {
            "description": "The organization's setup needs attention on Zeldoc's side; contact Zeldoc"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/orgs/{org_id}/invoices/{invoice_id}": {
      "get": {
        "tags": [
          "Invoices"
        ],
        "summary": "Get one invoice.",
        "operationId": "get_own_org_invoice",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "description": "Your organization id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "invoice_id",
            "in": "path",
            "description": "Invoice id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invoice",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceDTO"
                }
              }
            }
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Another organization's id, or invoices are not shared with your organization"
          },
          "404": {
            "description": "Not found, or the invoice belongs to another organization"
          },
          "409": {
            "description": "The organization's setup needs attention on Zeldoc's side; contact Zeldoc"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/orgs/{org_id}/invoices/{invoice_id}/pdf": {
      "get": {
        "tags": [
          "Invoices"
        ],
        "summary": "Download an invoice as PDF.",
        "operationId": "get_own_org_invoice_pdf",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "description": "Your organization id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "invoice_id",
            "in": "path",
            "description": "Invoice id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invoice PDF",
            "content": {
              "application/pdf": {}
            }
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Another organization's id, or invoices are not shared with your organization"
          },
          "404": {
            "description": "Not found, or the invoice belongs to another organization"
          },
          "409": {
            "description": "The organization's setup needs attention on Zeldoc's side; contact Zeldoc"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/orgs/{org_id}/key-usage": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Usage per API key.",
        "description": "Spend, tokens and requests for every API key of the organization over a\nperiod, highest spend first, each split by the models it called; plus\ntotals by model, by provider and by each of the organization's key fields.\nA key is usually held by one person, so per key is per person.\n\nPick at most one period style: `month`, `year`, `months`, or `start_date`\nwith `end_date`. Without any: the current month to date. Dates are UTC\ncalendar days, the end is clamped to today, and the response echoes the\nrange it covered. A range spans at most 366 days; backfill longer periods\nas successive ranges. For a daily sync, ask for yesterday as\n`start_date=end_date=YYYY-MM-DD`.\n\nSpend is USD only: a range can span months with different exchange rates.\nUse the monthly usage endpoint for DKK.",
        "operationId": "get_org_key_usage",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "description": "Your organization id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "month",
            "in": "query",
            "description": "A single calendar month, `YYYY-MM`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "year",
            "in": "query",
            "description": "A calendar year (Jan..Dec), clamped so it never runs past today.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "months",
            "in": "query",
            "description": "Trailing calendar months ending with the current one.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "start_date",
            "in": "query",
            "description": "First day to include, `YYYY-MM-DD`. Requires `end_date`.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "end_date",
            "in": "query",
            "description": "Last day to include, `YYYY-MM-DD`. Requires `start_date`.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Per-key and total usage for the period",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgKeyUsageDTO"
                }
              }
            }
          },
          "400": {
            "description": "Conflicting or malformed period parameters, or a range over 366 days; the body says which"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Another organization's id, or usage is not shared with your organization"
          },
          "409": {
            "description": "The organization's setup needs attention on Zeldoc's side; contact Zeldoc"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/orgs/{org_id}/monthly-usage": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Usage per calendar month.",
        "description": "Spend in USD and DKK plus token counts, one entry per month, oldest first.\nDKK uses the month's stored exchange rate; for the current month before\nits rate is stored, the most recent rate is used and `rate_estimated` is\ntrue. Without parameters: the trailing 12 months.",
        "operationId": "get_org_monthly_usage",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "description": "Your organization id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "months",
            "in": "query",
            "description": "Trailing calendar months to include, the current one included (default 12, max 60). Mutually exclusive with `year`.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "year",
            "in": "query",
            "description": "One calendar year (January to December). Mutually exclusive with `months`.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Monthly usage for the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgMonthlyUsageDTO"
                }
              }
            }
          },
          "400": {
            "description": "Both `months` and `year` were supplied"
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Another organization's id, or usage is not shared with your organization"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/orgs/{org_id}/plan-cost": {
      "get": {
        "tags": [
          "Subscription"
        ],
        "summary": "Monthly plan cost.",
        "description": "What the organization's subscription costs per month, line by line, in\nthe requested currency. Token usage is not included; see the usage\nendpoints.",
        "operationId": "get_org_plan_cost",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "description": "Your organization id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "currency",
            "in": "query",
            "description": "Currency to quote the plan in (DKK, EUR or USD). Defaults to DKK.",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/Currency"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The monthly plan cost",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgPlanCostDTO"
                }
              }
            }
          },
          "401": {
            "description": "Missing, expired or revoked token"
          },
          "403": {
            "description": "Another organization's id, or the subscription is not shared with your organization"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/partner/status": {
      "get": {
        "tags": [
          "Partners"
        ],
        "summary": "Every organization you serve and the keys you run there, each compared\nwith your recommended models.",
        "description": "A key is up to date when `has_recommended` is true. `missing_recommended`\nlists what to add (with `POST .../recommended` in the dashboard, or by\nediting the key's models), `not_allowed` what the organization may not use\n(contact Zeldoc), and `extra` what the key has beyond the list.",
        "operationId": "get_partner_status",
        "responses": {
          "200": {
            "description": "Every customer and the keys the partner runs there, each checked against the recommended models",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerStatusDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Not a partner"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "ApiKeyIdDTO": {
        "type": "string"
      },
      "Currency": {
        "type": "string",
        "description": "ISO 4217 currency code a price can be quoted in. Every price holds\na hand-set amount in each of these; nothing here is derived from an\nexchange rate.",
        "enum": [
          "DKK",
          "EUR",
          "USD"
        ]
      },
      "DailyUsageEntryDTO": {
        "type": "object",
        "description": "Usage on one calendar day (UTC), within a month of the monthly usage.\nSpend is in USD only; convert it with the month's rate\n(`dkk_spend / usd_spend` of the month) if you need DKK.",
        "required": [
          "date",
          "usd_spend",
          "total_tokens",
          "request_count"
        ],
        "properties": {
          "cache_creation_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens written into the provider's prompt cache; a subset of\n`prompt_tokens`."
          },
          "cache_read_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens served from the provider's prompt cache; a subset of\n`prompt_tokens`."
          },
          "completion_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "prompt_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "request_count": {
            "type": "integer",
            "format": "int64"
          },
          "total_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "usd_spend": {
            "type": "string"
          }
        }
      },
      "EmailAddressDTO": {
        "type": "string",
        "format": "email",
        "description": "An e-mail address, trimmed and lower-cased."
      },
      "InvoiceBuyerDTO": {
        "type": "object",
        "description": "Frozen buyer (\"Bill to\") details as they appeared at issue time.",
        "required": [
          "legal_name",
          "attention",
          "address_line1",
          "address_line2",
          "postal_code",
          "city",
          "country",
          "cvr",
          "vat",
          "ean",
          "payment_reference"
        ],
        "properties": {
          "address_line1": {
            "type": "string"
          },
          "address_line2": {
            "type": "string"
          },
          "attention": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "cvr": {
            "type": "string"
          },
          "ean": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email"
          },
          "legal_name": {
            "type": "string"
          },
          "payment_reference": {
            "type": "string"
          },
          "postal_code": {
            "type": "string"
          },
          "vat": {
            "type": "string"
          }
        }
      },
      "InvoiceDTO": {
        "type": "object",
        "description": "A full, immutable invoice. All money fields are integer øre.",
        "required": [
          "id",
          "org_id",
          "invoice_number",
          "status",
          "period_start",
          "period_end",
          "issued_at",
          "due_at",
          "currency",
          "language",
          "subscription_subtotal_cents",
          "usage_subtotal_cents",
          "subtotal_cents",
          "vat_rate_bps",
          "vat_cents",
          "total_cents",
          "seller",
          "buyer",
          "lines"
        ],
        "properties": {
          "buyer": {
            "$ref": "#/components/schemas/InvoiceBuyerDTO"
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "due_at": {
            "type": "string",
            "format": "date"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "invoice_number": {
            "type": "string"
          },
          "issued_at": {
            "type": "string",
            "format": "date-time"
          },
          "language": {
            "$ref": "#/components/schemas/InvoiceLanguage"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InvoiceLineDTO"
            }
          },
          "org_id": {
            "type": "string"
          },
          "period_end": {
            "type": "string",
            "format": "date"
          },
          "period_start": {
            "type": "string",
            "format": "date"
          },
          "seller": {
            "$ref": "#/components/schemas/InvoiceSellerDTO"
          },
          "status": {
            "$ref": "#/components/schemas/InvoiceStatus"
          },
          "subscription_subtotal_cents": {
            "type": "integer",
            "format": "int64"
          },
          "subtotal_cents": {
            "type": "integer",
            "format": "int64"
          },
          "total_cents": {
            "type": "integer",
            "format": "int64"
          },
          "usage_subtotal_cents": {
            "type": "integer",
            "format": "int64"
          },
          "usd_dkk_rate": {
            "type": [
              "string",
              "null"
            ]
          },
          "vat_cents": {
            "type": "integer",
            "format": "int64"
          },
          "vat_rate_bps": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "InvoiceLanguage": {
        "type": "string",
        "description": "The language an invoice is written in, frozen when it is issued.",
        "enum": [
          "da",
          "en"
        ]
      },
      "InvoiceLineDTO": {
        "type": "object",
        "description": "A single line on an invoice. Money is integer øre.",
        "required": [
          "sort_order",
          "kind",
          "description",
          "quantity",
          "unit_price_cents",
          "line_total_cents"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/InvoiceLineKind",
            "description": "What the line bills.\n\n`usage_provider` lines are informational: an \"of which <provider>\"\nsplit of the single `usage` line directly above them, summing exactly\nto it. They are not charged — totals are computed from plan + usage,\nnot from lines."
          },
          "line_total_cents": {
            "type": "integer",
            "format": "int64"
          },
          "quantity": {
            "type": "integer",
            "format": "int32"
          },
          "sort_order": {
            "type": "integer",
            "format": "int32"
          },
          "unit_price_cents": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "InvoiceLineKind": {
        "type": "string",
        "description": "What an invoice line bills: the plan, the month's usage (one line, or\none per upstream provider), or a developer's ZDev overage.",
        "enum": [
          "subscription",
          "usage",
          "usage_provider",
          "zdev_overage"
        ]
      },
      "InvoiceSellerDTO": {
        "type": "object",
        "description": "Frozen seller identity as it appeared on the invoice at issue time.",
        "required": [
          "legal_name",
          "address",
          "cvr",
          "vat",
          "email",
          "bank"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "bank": {
            "type": "string"
          },
          "cvr": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "legal_name": {
            "type": "string"
          },
          "vat": {
            "type": "string"
          }
        }
      },
      "InvoiceStatus": {
        "type": "string",
        "description": "Where an invoice stands: issued, or voided (kept, never deleted, and\nstamped VOID on its PDF).",
        "enum": [
          "issued",
          "void"
        ]
      },
      "InvoiceSummaryDTO": {
        "type": "object",
        "description": "Compact invoice for list views.",
        "required": [
          "id",
          "invoice_number",
          "status",
          "period_start",
          "issued_at",
          "due_at",
          "currency",
          "total_cents"
        ],
        "properties": {
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "due_at": {
            "type": "string",
            "format": "date"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "invoice_number": {
            "type": "string"
          },
          "issued_at": {
            "type": "string",
            "format": "date-time"
          },
          "period_start": {
            "type": "string",
            "format": "date"
          },
          "status": {
            "$ref": "#/components/schemas/InvoiceStatus"
          },
          "total_cents": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "KeyFieldDTO": {
        "type": "object",
        "description": "One field of an organization's key schema: every API key of the\norganization can carry a value for it. Lists of these are in display\norder.",
        "required": [
          "key",
          "display_name",
          "type"
        ],
        "properties": {
          "default_value": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/KeyFieldValueDTO",
                "description": "The value filled in for this field when a key is created in the\ndashboard, which the person creating it may change: a boolean, a text\nor an option's key, like any value of the field. `null` when the field\nhas none. A key created through the API without a value for the field\ndoes not get it."
              }
            ]
          },
          "display_name": {
            "type": "string",
            "description": "What the dashboard shows, e.g. \"Team name\"."
          },
          "key": {
            "$ref": "#/components/schemas/KeyFieldKeyDTO",
            "description": "Stable identifier the values are stored under, e.g. `team`."
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KeyFieldOptionDTO"
            },
            "description": "The choices of a `select` field, in the order to show them; empty\notherwise."
          },
          "required": {
            "type": "boolean",
            "description": "A key cannot be created, nor its fields saved, without a value here."
          },
          "sort_options_alphabetically": {
            "type": "boolean",
            "description": "A `select` field's choices are sorted by label (ignoring case) when\ntrue, the default; when false they keep the order they were given in."
          },
          "type": {
            "$ref": "#/components/schemas/KeyFieldType"
          }
        }
      },
      "KeyFieldKeyDTO": {
        "type": "string",
        "description": "The stable identifier of an organization's key field, such as `team` or\n`is_private`. It names the value on every key, so it never changes; the\ndisplay name next to it may."
      },
      "KeyFieldOptionDTO": {
        "type": "object",
        "description": "One choice of a select key field, e.g. `{\"key\": \"backend\", \"label\":\n\"Backend\"}`.",
        "required": [
          "key",
          "label"
        ],
        "properties": {
          "key": {
            "$ref": "#/components/schemas/KeyFieldOptionKeyDTO",
            "description": "Stable identifier stored on the keys that pick this option."
          },
          "label": {
            "type": "string",
            "description": "What the dashboard shows."
          }
        }
      },
      "KeyFieldOptionKeyDTO": {
        "type": "string",
        "description": "The stable identifier of one option of a select key field, such as\n`backend`. A key stores this, not the label, so renaming the option's\nlabel renames it on every key at once."
      },
      "KeyFieldType": {
        "type": "string",
        "description": "What a key field holds, and so which input the key editor shows.",
        "enum": [
          "text",
          "boolean",
          "select"
        ]
      },
      "KeyFieldValueDTO": {
        "oneOf": [
          {
            "type": "boolean"
          },
          {
            "type": "string"
          }
        ],
        "description": "One key field value on a key: a JSON boolean for a boolean field, a string\nfor a text field, and the chosen option's key for a select field."
      },
      "KeyProduct": {
        "type": "string",
        "description": "What an API key is for. Set when Zeldoc creates the key; a service key\ncan also be marked or unmarked later. Ordinary keys have none.",
        "enum": [
          "zconnect",
          "zdev",
          "service"
        ]
      },
      "ModelProduct": {
        "type": "string",
        "description": "The product a gateway model is sold under, as named on zeldoc.ai. A model\nwith no product is offered to nobody. An organization's allow-list is the\nmodels of the products on its settings page, plus whatever its team was\ngranted directly in the gateway.",
        "enum": [
          "zcore",
          "zdev",
          "zrouter"
        ]
      },
      "MonthlyUsageEntryDTO": {
        "type": "object",
        "description": "Usage for a single calendar month for one organization.\n\n`month` is the first day of the month. `dkk_spend` is null when no USD to\nDKK rate is available for that month; the USD figure is always there.\n\nFor the current (in-progress) month with no stored rate yet, `dkk_spend` is\nestimated from the most recent stored rate and `rate_estimated` is true.\nEarlier months with no stored rate keep `dkk_spend` null.",
        "required": [
          "month",
          "usd_spend",
          "rate_estimated",
          "total_tokens",
          "request_count"
        ],
        "properties": {
          "cache_creation_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens written into the provider's prompt cache. Also a subset\nof `prompt_tokens`; billed at a premium over the input rate."
          },
          "cache_read_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens served from the provider's prompt cache. A subset of\n`prompt_tokens`, not an addition to it; billed at a fraction of the\ninput rate, which is why a cache-heavy key can carry many tokens for\nlittle spend."
          },
          "completion_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "days": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DailyUsageEntryDTO"
            },
            "description": "The month day by day: one entry per calendar day (UTC), oldest first,\nup to today for the current month; days without usage are zero. The\ndays add up to the month's figures."
          },
          "dkk_spend": {
            "type": [
              "string",
              "null"
            ]
          },
          "month": {
            "type": "string",
            "format": "date",
            "description": "First day of the month this entry covers."
          },
          "prompt_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Input and output split of `total_tokens`, the two halves that are\npriced differently."
          },
          "rate_estimated": {
            "type": "boolean",
            "description": "True when `dkk_spend` was derived from a fallback rate (current month\nbefore its real rate is stored), false when from a stored rate or when\nthere is no DKK value."
          },
          "request_count": {
            "type": "integer",
            "format": "int64"
          },
          "total_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "usd_spend": {
            "type": "string"
          }
        }
      },
      "OrgKeyFieldGroupUsageDTO": {
        "type": "object",
        "description": "The usage of every key holding one value of a key field, e.g. all keys\nwhose team is Backend. The groups of a field add up to the report's\ntotals.",
        "required": [
          "key_count",
          "spend_usd",
          "prompt_tokens",
          "completion_tokens",
          "cache_read_input_tokens",
          "cache_creation_input_tokens",
          "total_tokens",
          "request_count",
          "zeldoc",
          "external"
        ],
        "properties": {
          "cache_creation_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "A subset of `prompt_tokens`, as on the key entries."
          },
          "cache_read_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "A subset of `prompt_tokens`, as on the key entries."
          },
          "completion_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "external": {
            "$ref": "#/components/schemas/OrgUsageSliceDTO",
            "description": "Traffic of these keys to every other model."
          },
          "key_count": {
            "type": "integer",
            "format": "int64",
            "description": "How many of the report's keys hold this value; zero for an option or\na yes/no nobody picked, listed so every choice shows."
          },
          "label": {
            "type": [
              "string",
              "null"
            ],
            "description": "The value for display: the option's label, the text itself, or\n\"Yes\" / \"No\". Null with `value`."
          },
          "prompt_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "request_count": {
            "type": "integer",
            "format": "int64"
          },
          "spend_usd": {
            "type": "string"
          },
          "total_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "value": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/KeyFieldValueDTO",
                "description": "The value the keys hold, as on `fields`: the text, true or false, or\nthe option's key. Null for the keys with no value, which includes\nkeys deleted since they spent."
              }
            ]
          },
          "zeldoc": {
            "$ref": "#/components/schemas/OrgUsageSliceDTO",
            "description": "Traffic of these keys to Zeldoc-hosted models."
          }
        }
      },
      "OrgKeyFieldUsageDTO": {
        "type": "object",
        "description": "The report's usage grouped by one key field: spend per team, private\nversus company keys, and so on.\n\nA select field lists every option in the schema's order and a boolean\ntrue then false, each even when no key holds it; a text field lists the\ntexts its keys hold, highest spend first. The group of keys with no value\ncomes last, and only when there are such keys. The groups add up to the\nreport's totals. Keys are grouped by the values they hold now, not when\nthe usage happened.",
        "required": [
          "key",
          "display_name",
          "type",
          "groups"
        ],
        "properties": {
          "display_name": {
            "type": "string"
          },
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrgKeyFieldGroupUsageDTO"
            }
          },
          "key": {
            "$ref": "#/components/schemas/KeyFieldKeyDTO",
            "description": "The field's stable key, as on each entry's `fields`."
          },
          "type": {
            "$ref": "#/components/schemas/KeyFieldType"
          }
        }
      },
      "OrgKeyModelUsageDTO": {
        "type": "object",
        "description": "Usage one API key drove on a single model over the reported period.\nSpend is in USD.",
        "required": [
          "model",
          "spend_usd",
          "prompt_tokens",
          "completion_tokens",
          "total_tokens",
          "request_count"
        ],
        "properties": {
          "cache_creation_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens written into the provider's prompt cache. Also a subset\nof `prompt_tokens`; billed at a premium over the input rate."
          },
          "cache_read_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens served from the provider's prompt cache. A subset of\n`prompt_tokens`, not an addition to it; billed at a fraction of the\ninput rate, which is why a cache-heavy key can carry many tokens for\nlittle spend."
          },
          "completion_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "model": {
            "type": "string",
            "description": "The model as named in the request, e.g. \"zeldoc/zdev\" or\n\"claude-opus-4-8\"."
          },
          "prompt_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "request_count": {
            "type": "integer",
            "format": "int64"
          },
          "spend_usd": {
            "type": "string"
          },
          "total_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "zeldoc_hosted": {
            "type": "boolean",
            "description": "True for a model Zeldoc hosts itself. Covered by the subscription, so\nits spend is zero; it still counts tokens and requests, and rolls into\nthe entry's `zeldoc` slice."
          }
        }
      },
      "OrgKeyUsageDTO": {
        "type": "object",
        "description": "Per-key spend and model usage for one organization over a date range.\n\n`start_date` and `end_date` echo back the resolved, inclusive range that was\nactually queried, so a caller polling this on a schedule can record exactly\nwhich days a response covers rather than re-deriving it from its own request.\n\nAll spend is USD. Unlike the monthly usage endpoint there is no DKK figure:\nthe stored USD->DKK rates are per calendar month, and an arbitrary date range\ncan span several months, so a single converted total would silently blend\nrates. Convert per month via `/api/orgs/{org_id}/monthly-usage` when DKK is\nneeded.",
        "required": [
          "org_id",
          "start_date",
          "end_date",
          "keys",
          "totals"
        ],
        "properties": {
          "end_date": {
            "type": "string",
            "format": "date",
            "description": "Last day covered, inclusive."
          },
          "key_fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KeyFieldDTO"
            },
            "description": "The organization's key fields in display order: the labels for each\nentry's `fields`, so the report reads on its own."
          },
          "keys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrgKeyUsageEntryDTO"
            }
          },
          "org_id": {
            "type": "string",
            "description": "Organization id."
          },
          "start_date": {
            "type": "string",
            "format": "date",
            "description": "First day covered, inclusive."
          },
          "totals": {
            "$ref": "#/components/schemas/OrgKeyUsageTotalsDTO"
          }
        }
      },
      "OrgKeyUsageEntryDTO": {
        "type": "object",
        "description": "One API key's usage over the reported period, split by the models it called.\n\n`models` is empty for a key with no recorded activity in the period. The\nper-model figures can sum to slightly less than the key total when the\ngateway recorded usage without attributing it to a model.\n\n`zeldoc` and `external` split the key's tokens and requests by where they\nwent: Zeldoc's own self-hosted models versus third-party providers. They\nalways add up to the key's figures; usage attributed to no model at all is\ncounted as external.\n\nA key deleted since it spent is still reported, named \"(deleted key)\" or\nby its last alias, without `fields`, `product` or `recipient_email`.",
        "required": [
          "id",
          "name",
          "key_prefix",
          "spend_usd",
          "prompt_tokens",
          "completion_tokens",
          "total_tokens",
          "request_count",
          "models"
        ],
        "properties": {
          "cache_creation_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens written into the provider's prompt cache. Also a subset\nof `prompt_tokens`; billed at a premium over the input rate."
          },
          "cache_read_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens served from the provider's prompt cache. A subset of\n`prompt_tokens`, not an addition to it; billed at a fraction of the\ninput rate, which is why a cache-heavy key can carry many tokens for\nlittle spend."
          },
          "completion_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "external": {
            "$ref": "#/components/schemas/OrgUsageSliceDTO",
            "description": "Traffic to every other model: what left for third-party providers."
          },
          "fields": {
            "type": "object",
            "description": "The key's key field values by field key, for the fields the\norganization has now (`key_fields` on the report). Empty for a key\ndeleted since it spent. These are the key's values today, not when\nthe usage happened.",
            "additionalProperties": {
              "$ref": "#/components/schemas/KeyFieldValueDTO"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "id": {
            "$ref": "#/components/schemas/ApiKeyIdDTO"
          },
          "key_prefix": {
            "type": "string"
          },
          "models": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrgKeyModelUsageDTO"
            }
          },
          "name": {
            "type": "string"
          },
          "product": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/KeyProduct",
                "description": "`zconnect` for a ZConnect key, `zdev` for a ZDev key, null for an\nordinary key or one deleted since it spent."
              }
            ]
          },
          "prompt_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "recipient_email": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/EmailAddressDTO",
                "description": "Who the key was sent to, for a key handed out from the ZConnect page;\notherwise null."
              }
            ]
          },
          "request_count": {
            "type": "integer",
            "format": "int64"
          },
          "spend_usd": {
            "type": "string"
          },
          "total_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "zeldoc": {
            "$ref": "#/components/schemas/OrgUsageSliceDTO",
            "description": "Traffic to Zeldoc-hosted models, the subscription-covered part."
          }
        }
      },
      "OrgKeyUsageTotalsDTO": {
        "type": "object",
        "description": "Period totals across every key in the organization, including the split\nacross the models those keys called.",
        "required": [
          "spend_usd",
          "prompt_tokens",
          "completion_tokens",
          "total_tokens",
          "request_count",
          "models"
        ],
        "properties": {
          "by_field": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrgKeyFieldUsageDTO"
            },
            "description": "The same totals grouped by each of the organization's key fields, in\nthe order of `key_fields`: spend per team, private versus company\nkeys. Empty when the organization has no key fields."
          },
          "cache_creation_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens written into the provider's prompt cache. Also a subset\nof `prompt_tokens`; billed at a premium over the input rate."
          },
          "cache_read_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens served from the provider's prompt cache. A subset of\n`prompt_tokens`, not an addition to it; billed at a fraction of the\ninput rate, which is why a cache-heavy key can carry many tokens for\nlittle spend."
          },
          "completion_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "external": {
            "$ref": "#/components/schemas/OrgUsageSliceDTO",
            "description": "Traffic to third-party models across every key."
          },
          "models": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrgModelUsageDTO"
            },
            "description": "Every model the organization used in the period, highest spend first,\nthen most tokens first so zero-priced Zeldoc-hosted models still order\nby size. Empty when no key recorded activity. Like the per-key\nbreakdown these can sum to slightly less than the totals above, because\nusage is occasionally recorded without a model."
          },
          "prompt_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "providers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrgProviderUsageDTO"
            },
            "description": "Every upstream provider the organization's usage was routed to in the\nperiod, highest spend first: the cut above `models`. Zeldoc-hosted\ntraffic may appear as `hosted_vllm` at zero spend, but not reliably;\nuse `zeldoc` / `external` for that split. Empty when nothing was\nrecorded."
          },
          "request_count": {
            "type": "integer",
            "format": "int64"
          },
          "spend_usd": {
            "type": "string"
          },
          "total_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "zeldoc": {
            "$ref": "#/components/schemas/OrgUsageSliceDTO",
            "description": "Traffic to Zeldoc-hosted models across every key. Together with\n`external` this adds up to the totals above."
          }
        }
      },
      "OrgModelUsageDTO": {
        "type": "object",
        "description": "One model's usage across the whole organization over the reported period:\nthe per-key `models` breakdown rolled up across every key. Spend is USD.",
        "required": [
          "model",
          "spend_usd",
          "prompt_tokens",
          "completion_tokens",
          "total_tokens",
          "request_count"
        ],
        "properties": {
          "cache_creation_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens written into the provider's prompt cache. Also a subset\nof `prompt_tokens`; billed at a premium over the input rate."
          },
          "cache_read_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens served from the provider's prompt cache. A subset of\n`prompt_tokens`, not an addition to it; billed at a fraction of the\ninput rate, which is why a cache-heavy key can carry many tokens for\nlittle spend."
          },
          "completion_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "model": {
            "type": "string",
            "description": "The model as named in the request, e.g. \"zeldoc/zdev\" or\n\"claude-opus-4-8\"."
          },
          "prompt_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "request_count": {
            "type": "integer",
            "format": "int64"
          },
          "spend_usd": {
            "type": "string"
          },
          "total_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "zeldoc_hosted": {
            "type": "boolean",
            "description": "True for a model Zeldoc hosts itself. Covered by the subscription, so\nits spend is zero; it still counts tokens and requests, and rolls into\nthe totals' `zeldoc` slice."
          }
        }
      },
      "OrgMonthlyUsageDTO": {
        "type": "object",
        "description": "Monthly usage for a single organization.\n\n`months` holds one entry per calendar month, oldest first. `summary` holds\nperiod totals and the change against the previous month.\n`available_years` lists the calendar years the organization can have data\nfor, from the year it was created to the current one.",
        "required": [
          "org_id",
          "months",
          "summary",
          "available_years"
        ],
        "properties": {
          "available_years": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },
          "months": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MonthlyUsageEntryDTO"
            }
          },
          "org_id": {
            "type": "string",
            "description": "Organization id."
          },
          "summary": {
            "$ref": "#/components/schemas/OrgUsageSummaryDTO"
          }
        }
      },
      "OrgPlanCostDTO": {
        "type": "object",
        "description": "The organization's monthly subscription cost, from its products, its\nZCore plan, the ZDev seats it has ordered and any price agreed with it. All money values are minor units of\n`currency` (e.g. 149000 = 1.490,00 DKK), taken from the price set in that\ncurrency, never converted.",
        "required": [
          "currency",
          "seats",
          "lines",
          "missing",
          "total_monthly_cents"
        ],
        "properties": {
          "currency": {
            "$ref": "#/components/schemas/Currency",
            "description": "Currency of all amounts (ISO 4217): the one requested (DKK by default)."
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrgPlanCostLineDTO"
            },
            "description": "One line per product the organization has that has a price."
          },
          "missing": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrgPlanCostMissingDTO"
            },
            "description": "Products the organization has that have no price yet."
          },
          "seats": {
            "type": "integer",
            "format": "int32",
            "description": "ZDev seats ordered, across the plans. Every ordered seat is billed,\nused or not."
          },
          "total_monthly_cents": {
            "type": "integer",
            "format": "int64",
            "description": "Sum of all `line_total_cents`, in minor units."
          },
          "zcore_plan": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ZCorePlan",
                "description": "The organization's ZCore plan; null when it has none."
              }
            ]
          }
        }
      },
      "OrgPlanCostLineDTO": {
        "type": "object",
        "description": "A single billable line of an organization's monthly plan cost.",
        "required": [
          "service",
          "type",
          "is_per_user",
          "unit_price_cents",
          "quantity",
          "line_total_cents"
        ],
        "properties": {
          "custom_price": {
            "type": "boolean",
            "description": "True when the price is one agreed with the organization rather than\nthe list price."
          },
          "is_per_user": {
            "type": "boolean",
            "description": "When true, the line is billed per seat (`quantity` = seats); otherwise flat."
          },
          "line_total_cents": {
            "type": "integer",
            "format": "int64",
            "description": "`unit_price_cents * quantity`, in minor units."
          },
          "period": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/PlanCostPeriodDTO",
                "description": "Set when the line covers only part of a month (seats added\nmid-month, on an invoice); null for a whole month."
              }
            ]
          },
          "plan": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ZDevPlan",
                "description": "The ZDev plan of a ZDev line (one line per plan with seats); null on\nother products."
              }
            ]
          },
          "quantity": {
            "type": "integer",
            "format": "int32",
            "description": "Seats for per-user lines, otherwise 1."
          },
          "service": {
            "$ref": "#/components/schemas/PricingService"
          },
          "type": {
            "$ref": "#/components/schemas/PricingType"
          },
          "unit_price_cents": {
            "type": "integer",
            "format": "int32",
            "description": "Price of one unit, in minor units (e.g. 149000 = 1.490,00 DKK). For a\nline covering part of a month, the price for those days."
          },
          "zcore_plan": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ZCorePlan",
                "description": "The ZCore plan of a ZCore line at its list price; null on other\nproducts and on an agreed price."
              }
            ]
          }
        }
      },
      "OrgPlanCostMissingDTO": {
        "type": "object",
        "description": "A product the organization has that has no price yet (ZCore without a\nplan or an agreed price, or a ZDev plan it has seats of), so it is not\nin the plan cost.",
        "required": [
          "service",
          "type"
        ],
        "properties": {
          "plan": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ZDevPlan",
                "description": "The ZDev plan without a price, for ZDev; null on other products."
              }
            ]
          },
          "service": {
            "$ref": "#/components/schemas/PricingService"
          },
          "type": {
            "$ref": "#/components/schemas/PricingType"
          }
        }
      },
      "OrgProviderUsageDTO": {
        "type": "object",
        "description": "One upstream provider's usage across the whole organization over the\nreported period: the coarser cut above the models, for \"how much went to\nOpenAI versus Anthropic\". Ordered by spend, highest first. Spend is USD.",
        "required": [
          "provider",
          "spend_usd",
          "prompt_tokens",
          "completion_tokens",
          "total_tokens",
          "request_count"
        ],
        "properties": {
          "cache_creation_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens written into the provider's prompt cache. Also a subset\nof `prompt_tokens`; billed at a premium over the input rate."
          },
          "cache_read_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens served from the provider's prompt cache. A subset of\n`prompt_tokens`, not an addition to it; billed at a fraction of the\ninput rate, which is why a cache-heavy key can carry many tokens for\nlittle spend."
          },
          "completion_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "prompt_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "provider": {
            "type": "string",
            "description": "The provider's slug, e.g. `openai`, `anthropic`, `gemini`, or\n`hosted_vllm` for Zeldoc-hosted models."
          },
          "request_count": {
            "type": "integer",
            "format": "int64"
          },
          "spend_usd": {
            "type": "string"
          },
          "total_tokens": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "OrgUsageSliceDTO": {
        "type": "object",
        "description": "Tokens and requests for one side of the Zeldoc-hosted / external split.\n\nUsed in pairs on the per-key entry and on the period totals: `zeldoc` is the\ntraffic that went to Zeldoc's own self-hosted models (covered by the\nsubscription and priced at zero), `external` is everything\nelse — the traffic that left for OpenAI, Anthropic, Google and the rest.\nThe two always add up to the row they sit on, so \"what share went out into\nthe world\" is one division.\n\nNo spend figure: the Zeldoc side is zero by construction, and the external\nside is the row's own `spend_usd`.",
        "required": [
          "prompt_tokens",
          "completion_tokens",
          "total_tokens",
          "request_count"
        ],
        "properties": {
          "cache_creation_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens written into the provider's prompt cache. Also a subset\nof `prompt_tokens`; billed at a premium over the input rate."
          },
          "cache_read_input_tokens": {
            "type": "integer",
            "format": "int64",
            "description": "Prompt tokens served from the provider's prompt cache. A subset of\n`prompt_tokens`, not an addition to it; billed at a fraction of the\ninput rate, which is why a cache-heavy key can carry many tokens for\nlittle spend."
          },
          "completion_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "prompt_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "request_count": {
            "type": "integer",
            "format": "int64"
          },
          "total_tokens": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "OrgUsageSummaryDTO": {
        "type": "object",
        "description": "Period totals (over all returned months) plus the month-over-month percentage\nchange.\n\nEach `*_change_pct` compares the **current calendar month** against the\n**immediately previous month**. Because the current month is in progress, its\ntotals are **projected to a full-month run-rate** (so-far / days-elapsed *\ndays-in-month) before the comparison, so the delta reflects the trend rather\nthan a partial-vs-full understatement. The projection affects only this delta,\nnot the actual values in `months[]`.\n\n`None` when either month is absent from the returned window (e.g. a past year\nwas selected), or when the previous month is zero (no baseline).",
        "required": [
          "total_usd_spend",
          "total_requests",
          "total_tokens"
        ],
        "properties": {
          "requests_change_pct": {
            "type": [
              "string",
              "null"
            ]
          },
          "tokens_change_pct": {
            "type": [
              "string",
              "null"
            ]
          },
          "total_dkk_spend": {
            "type": [
              "string",
              "null"
            ]
          },
          "total_requests": {
            "type": "integer",
            "format": "int64"
          },
          "total_tokens": {
            "type": "integer",
            "format": "int64"
          },
          "total_usd_spend": {
            "type": "string"
          },
          "usd_spend_change_pct": {
            "type": [
              "string",
              "null"
            ],
            "description": "Percent change of the current month vs the previous month (e.g. -25.7)."
          }
        }
      },
      "PartnerCustomerDTO": {
        "type": "object",
        "description": "An organization a partner serves.",
        "required": [
          "org_id",
          "name",
          "key_count"
        ],
        "properties": {
          "key_count": {
            "type": "integer",
            "minimum": 0
          },
          "name": {
            "type": "string"
          },
          "org_id": {
            "type": "string"
          }
        }
      },
      "PartnerCustomerKeysDTO": {
        "type": "object",
        "description": "One organization you serve and the keys you run there.",
        "required": [
          "customer",
          "allowed_models",
          "keys"
        ],
        "properties": {
          "allowed_models": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PartnerModelDTO"
            },
            "description": "The models a key there may have; the recommended ones are marked."
          },
          "customer": {
            "$ref": "#/components/schemas/PartnerCustomerDTO"
          },
          "keys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PartnerKeyDTO"
            }
          }
        }
      },
      "PartnerKeyDTO": {
        "type": "object",
        "description": "A key you run, compared with your recommended models.",
        "required": [
          "id",
          "name",
          "key_prefix",
          "models",
          "missing_recommended",
          "not_allowed",
          "extra",
          "has_recommended",
          "no_longer_offered",
          "profile_id",
          "profile_name",
          "locked",
          "recommended_models",
          "created_at"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "extra": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "has_recommended": {
            "type": "boolean"
          },
          "id": {
            "type": "string"
          },
          "key_prefix": {
            "type": "string"
          },
          "locked": {
            "type": "boolean",
            "description": "The profile is a fixed set Zeldoc keeps: the models cannot be changed."
          },
          "missing_recommended": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Recommended and allowed here, but not on the key."
          },
          "models": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "name": {
            "type": "string"
          },
          "no_longer_offered": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "On the key but no longer offered to the organization, e.g. an older\nversion. It stays on the key until you remove it."
          },
          "not_allowed": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Recommended, but not on this organization's allow-list."
          },
          "profile_id": {
            "$ref": "#/components/schemas/PartnerProfileIdDTO"
          },
          "profile_name": {
            "type": "string"
          },
          "recommended_models": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What this key is checked against: its profile's recommendation."
          }
        }
      },
      "PartnerModelDTO": {
        "type": "object",
        "required": [
          "id",
          "name",
          "zconnect"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "product": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ModelProduct"
              }
            ]
          },
          "zconnect": {
            "type": "boolean",
            "description": "On the allow-list as one of the organization's ZConnect models."
          }
        }
      },
      "PartnerProfileDTO": {
        "type": "object",
        "description": "What one kind of key is checked against, e.g. \"Chat\" or \"Vault\".",
        "required": [
          "id",
          "name",
          "follows_zrouter",
          "recommended",
          "key_count"
        ],
        "properties": {
          "follows_zrouter": {
            "type": "boolean",
            "description": "The recommendation follows the ZRouter models, so a new one is\nrecommended at once. Otherwise it is a fixed set Zeldoc keeps, and\nthe keys' models cannot be changed by the partner."
          },
          "id": {
            "$ref": "#/components/schemas/PartnerProfileIdDTO"
          },
          "key_count": {
            "type": "integer",
            "minimum": 0
          },
          "name": {
            "type": "string"
          },
          "recommended": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "PartnerProfileIdDTO": {
        "type": "string",
        "format": "uuid"
      },
      "PartnerStatusDTO": {
        "type": "object",
        "description": "Every customer of the partner and the keys it runs there, each checked\nagainst the recommended models.",
        "required": [
          "org_id",
          "name",
          "profiles",
          "customers",
          "key_count",
          "keys_missing_recommended"
        ],
        "properties": {
          "customers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PartnerCustomerKeysDTO"
            }
          },
          "key_count": {
            "type": "integer",
            "minimum": 0
          },
          "keys_missing_recommended": {
            "type": "integer",
            "description": "Keys missing a recommended model the customer may use.",
            "minimum": 0
          },
          "name": {
            "type": "string"
          },
          "org_id": {
            "type": "string",
            "description": "The partner's own organization id."
          },
          "profiles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PartnerProfileDTO"
            },
            "description": "What each kind of key is checked against."
          }
        }
      },
      "PlanCostPeriodDTO": {
        "type": "object",
        "description": "The days of a month a plan cost line covers, when it is less than the\nwhole month: seats added mid-month are billed from the day they were\nadded, for those days only.",
        "required": [
          "first_day",
          "last_day"
        ],
        "properties": {
          "first_day": {
            "type": "string",
            "format": "date"
          },
          "last_day": {
            "type": "string",
            "format": "date"
          }
        }
      },
      "PricingService": {
        "type": "string",
        "description": "Service or product line that can be priced.",
        "enum": [
          "private_llm",
          "llm_router",
          "zcontrol",
          "zconnect"
        ]
      },
      "PricingType": {
        "type": "string",
        "description": "Type or sub-offering within a priced service (e.g. Coding vs Assistant).",
        "enum": [
          "coding",
          "assistant",
          "public_models",
          "management",
          "integrations"
        ]
      },
      "ZCorePlan": {
        "type": "string",
        "description": "A ZCore plan, as sold on zeldoc.ai. It sets the organization's monthly\nZCore price.",
        "enum": [
          "starter",
          "small",
          "medium",
          "large"
        ]
      },
      "ZDevPlan": {
        "type": "string",
        "description": "A ZDev plan. Seats are ordered per plan, and each person with a seat\nholds a seat of one plan.",
        "enum": [
          "go",
          "pro",
          "max"
        ]
      }
    },
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "A reporting token (`zdt_...`) created by an organization admin in the dashboard."
      }
    }
  },
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Usage",
      "description": "Token usage and spend, per key and per month."
    },
    {
      "name": "Subscription",
      "description": "What the organization's plan costs."
    },
    {
      "name": "Invoices",
      "description": "Invoices issued to the organization."
    },
    {
      "name": "Partners",
      "description": "For partners running an app for other organizations: their keys there, checked against the recommended models."
    }
  ]
}