{
  "openapi": "3.1.0",
  "info": {
    "title": "A3JM Estate Data API",
    "version": "1.0.1",
    "summary": "Read-only, pull-mode source for the Excess Platform (utilisation, inventory, cost, hierarchy).",
    "description": "Read-only facade over A3JM's locally held estate database. Entities and field names follow the\nExcess Platform Data Exchange Pack v1.0 §4 (Person, Business unit, Product, Component, Hypervisor,\nVM, Usage sample, Finance, Data centre) so the platform's own validator applies unchanged.\n\n* Every identifier is a stable **pseudonym** issued by A3JM (hosts, VMs, networks, people). The\n  mapping to real names never leaves A3JM. Identifiers are unique and never reused.\n* Only `GET`. Any other method returns 405. The upstream collection runs with read-only roles.\n* The API serves from its own store, refreshed on the cadence shown per dataset in `/datasets`.\n  Nothing here reaches A3JM's live systems.\n* Names and e-mail addresses are never present. Free-text fields are curated, never copied from\n  internal systems.\n* Pack domains with no data at A3JM (Kubernetes inventory/usage/cost, FOCUS cloud billing) have no\n  endpoints; `/datasets` lists them as `not_applicable` so the completeness checker records the gap\n  explicitly rather than as missing data.\n",
    "contact": {
      "name": "A3JM API support",
      "email": "api@a3jm.com"
    },
    "x-pack-version": "1.0 (2026-10-11)"
  },
  "servers": [
    {
      "url": "https://api.a3jm.com/v1"
    }
  ],
  "security": [
    {
      "apiKey": [],
      "bearerToken": []
    }
  ],
  "tags": [
    {
      "name": "meta"
    },
    {
      "name": "hierarchy",
      "description": "People",
      "business units": null,
      "cost centres": null,
      "products": null,
      "ownership (pack §4 Person": null,
      "Business unit": null,
      "Project and product)": null
    },
    {
      "name": "components",
      "description": "Components with cost and lifecycle dates (pack §4 Component",
      "Finance": null,
      "Lifecycle)": null
    },
    {
      "name": "infrastructure",
      "description": "Hypervisors",
      "VMs": null,
      "data centres (pack §4 Hypervisor and VM": null,
      "Regions and data centres)": null
    },
    {
      "name": "usage",
      "description": "Usage samples per VM and host",
      "level 0 (pack §4 Usage samples)": null
    },
    {
      "name": "finance",
      "description": "Contracts and third-party costs (pack §4 Finance)"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "meta"
        ],
        "operationId": "getHealth",
        "security": [],
        "summary": "API status and store freshness",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "store_observed_at",
                    "publisher_last_seen"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "degraded"
                      ]
                    },
                    "store_observed_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "null until the first ingest"
                    },
                    "publisher_last_seen": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/me": {
      "get": {
        "tags": [
          "meta"
        ],
        "operationId": "getMe",
        "summary": "The calling key: partner, scopes, expiry, rate limit, 24-hour usage, sandbox flag",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "key_id",
                    "partner",
                    "scopes",
                    "rate_per_min",
                    "requests_24h",
                    "errors_24h",
                    "sandbox"
                  ],
                  "additionalProperties": false,
                  "properties": {
                    "key_id": {
                      "type": "string"
                    },
                    "partner": {
                      "type": "string"
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "expires_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "sandbox": {
                      "type": "boolean",
                      "description": "true when the key is served the synthetic sandbox estate"
                    },
                    "rate_per_min": {
                      "type": "integer"
                    },
                    "requests_24h": {
                      "type": "integer"
                    },
                    "errors_24h": {
                      "type": "integer"
                    },
                    "last_used_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/datasets": {
      "get": {
        "tags": [
          "meta"
        ],
        "operationId": "listDatasets",
        "summary": "Every dataset with cadence, level of detail, last refresh and row count",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Dataset"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/collection-runs": {
      "get": {
        "tags": [
          "meta"
        ],
        "operationId": "listCollectionRuns",
        "summary": "Collection runs (pack §9): what was read, rows written, source, watermark",
        "parameters": [
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Page"
                    },
                    {
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CollectionRun"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/people": {
      "get": {
        "tags": [
          "hierarchy"
        ],
        "operationId": "listPeople",
        "summary": "People (pack §4 Person). Pseudonymous ids only; no name, no e-mail.",
        "x-scope": "hierarchy:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/updatedSince"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Page"
                    },
                    {
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Person"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenScope"
          }
        }
      }
    },
    "/business-units": {
      "get": {
        "tags": [
          "hierarchy"
        ],
        "operationId": "listBusinessUnits",
        "summary": "Business units and cost centres (pack §4). One tree per kind.",
        "x-scope": "hierarchy:read",
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "business_unit",
                "cost_centre"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "observed_at"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BusinessUnit"
                      }
                    },
                    "observed_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenScope"
          }
        }
      }
    },
    "/products": {
      "get": {
        "tags": [
          "hierarchy"
        ],
        "operationId": "listProducts",
        "summary": "Products with project, business unit, criticality and the three owners (pack §4 Project and product)",
        "x-scope": "hierarchy:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Page"
                    },
                    {
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Product"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenScope"
          }
        }
      }
    },
    "/components": {
      "get": {
        "tags": [
          "components"
        ],
        "operationId": "listComponents",
        "summary": "Components per product with monthly cost, capex/opex and lifecycle dates (pack §4 Component)",
        "x-scope": "components:read",
        "parameters": [
          {
            "name": "product_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/ComponentKind"
            }
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Page"
                    },
                    {
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Component"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenScope"
          }
        }
      }
    },
    "/data-centres": {
      "get": {
        "tags": [
          "infrastructure"
        ],
        "operationId": "listDataCentres",
        "summary": "Regions and data centres with role and backup mode (pack §4 Regions and data centres)",
        "x-scope": "infrastructure:read",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "observed_at"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DataCentre"
                      }
                    },
                    "observed_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenScope"
          }
        }
      }
    },
    "/hypervisors": {
      "get": {
        "tags": [
          "infrastructure"
        ],
        "operationId": "listHypervisors",
        "summary": "Hypervisors with capacity, asset cost and lifecycle dates (pack §4 Hypervisor)",
        "x-scope": "infrastructure:read",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "observed_at"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Hypervisor"
                      }
                    },
                    "observed_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenScope"
          }
        }
      }
    },
    "/vms": {
      "get": {
        "tags": [
          "infrastructure"
        ],
        "operationId": "listVms",
        "summary": "Virtual machines (incl. the hosted VPS as a VM on a `cloud` hypervisor) with product mapping (pack §4 VM)",
        "x-scope": "infrastructure:read",
        "parameters": [
          {
            "name": "hypervisor_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "power_state",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "running",
                "stopped",
                "suspended"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "observed_at"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Vm"
                      }
                    },
                    "observed_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenScope"
          }
        }
      }
    },
    "/usage-samples": {
      "get": {
        "tags": [
          "usage"
        ],
        "operationId": "listUsageSamples",
        "summary": "Usage samples per VM (level 0, 5-minute interval, 30-day history; pack §4 Usage samples)",
        "description": "`resource_id` is a `vm_id` from `/vms`. Samples are regular 5-minute aggregates of 30-second\nscrapes (mean within the interval; `cpu_usage_cores_max` carries the interval maximum so a\np95 computed here is conservative). Window maximum 7 days per call; use `cursor` to continue.\n",
        "x-scope": "usage:read",
        "parameters": [
          {
            "name": "resource_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "name": "interval",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "5m",
                "15m",
                "1h"
              ],
              "default": "5m"
            }
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Page"
                    },
                    {
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/UsageSample"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidParameter"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/usage-daily": {
      "get": {
        "tags": [
          "usage"
        ],
        "operationId": "listUsageDaily",
        "summary": "Level 1 convenience: daily average and p95 per VM, so the platform need not pull every sample",
        "x-scope": "usage:read",
        "parameters": [
          {
            "name": "resource_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "observed_at"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/UsageDaily"
                      }
                    },
                    "observed_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenScope"
          }
        }
      }
    },
    "/finance/contracts": {
      "get": {
        "tags": [
          "finance"
        ],
        "operationId": "listContracts",
        "summary": "Licences, contracts and third-party costs (pack §4 Finance). Monthly cadence.",
        "x-scope": "finance:read",
        "parameters": [
          {
            "name": "product_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "active_on",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "currency",
                    "observed_at"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Contract"
                      }
                    },
                    "currency": {
                      "type": "string",
                      "description": "ISO 4217",
                      "stated once per tenant": null
                    },
                    "observed_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenScope"
          }
        }
      }
    },
    "/export/{dataset}": {
      "get": {
        "tags": [
          "meta"
        ],
        "operationId": "exportDataset",
        "summary": "Bulk extract of one dataset as NDJSON or CSV in the pack's file-template layout",
        "x-scope": "export:read",
        "parameters": [
          {
            "name": "dataset",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "people",
                "business_units",
                "products",
                "components",
                "data_centres",
                "hypervisors",
                "vms",
                "usage_samples",
                "usage_daily",
                "contracts",
                "collection_runs"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ndjson",
                "csv"
              ],
              "default": "ndjson"
            }
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/x-ndjson": {
                "schema": {
                  "type": "string"
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenScope"
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": [
          "meta"
        ],
        "operationId": "getOpenApi",
        "security": [],
        "summary": "This specification",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "The user key (public identifier of the tenant key). Safe to log."
      },
      "bearerToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "The API token (secret). Stored by A3JM only as a hash. Issued, rotated and revoked through\nmaker-checker. Mutual TLS 1.3 with a platform-issued client certificate can be required in\naddition at the edge; negotiable (pack §10).\n"
      }
    },
    "parameters": {
      "from": {
        "name": "from",
        "in": "query",
        "schema": {
          "type": "string",
          "format": "date-time"
        },
        "description": "Inclusive start, UTC. Default 24 hours before `to`."
      },
      "to": {
        "name": "to",
        "in": "query",
        "schema": {
          "type": "string",
          "format": "date-time"
        },
        "description": "Exclusive end, UTC. Default now."
      },
      "updatedSince": {
        "name": "updated_since",
        "in": "query",
        "schema": {
          "type": "string",
          "format": "date-time"
        },
        "description": "Daily-delta support (pack §3 People cadence); returns records changed since."
      },
      "cursor": {
        "name": "cursor",
        "in": "query",
        "schema": {
          "type": "string"
        }
      },
      "limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000,
          "default": 500
        }
      }
    },
    "schemas": {
      "Page": {
        "type": "object",
        "required": [
          "items",
          "next_cursor",
          "observed_at"
        ],
        "properties": {
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "observed_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the store last refreshed this dataset"
          }
        }
      },
      "Dataset": {
        "type": "object",
        "required": [
          "name",
          "status",
          "cadence_seconds",
          "level",
          "last_refresh",
          "rows"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "live",
              "stale",
              "not_applicable"
            ],
            "description": "not_applicable = pack domain with no data at A3JM (e.g. kubernetes_*)"
          },
          "cadence_seconds": {
            "type": [
              "integer",
              "null"
            ]
          },
          "level": {
            "type": [
              "integer",
              "null"
            ],
            "enum": [
              0,
              1,
              2,
              null
            ],
            "description": "Pack §5 level of detail"
          },
          "last_refresh": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "rows": {
            "type": "integer"
          },
          "retention_days": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      },
      "CollectionRun": {
        "type": "object",
        "required": [
          "run_id",
          "dataset",
          "source_class",
          "started_at",
          "finished_at",
          "rows_written",
          "watermark",
          "status"
        ],
        "additionalProperties": false,
        "properties": {
          "run_id": {
            "type": "string"
          },
          "dataset": {
            "type": "string"
          },
          "source_class": {
            "type": "string",
            "description": "Generic class (metrics_store",
            "hypervisor_api": null,
            "identity_provider": null,
            "inventory": null,
            "finance_file); never a hostname": null
          },
          "started_at": {
            "type": "string",
            "format": "date-time"
          },
          "finished_at": {
            "type": "string",
            "format": "date-time"
          },
          "rows_written": {
            "type": "integer"
          },
          "watermark": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "partial",
              "failed"
            ]
          }
        }
      },
      "Person": {
        "description": "Pack §4 Person. Pseudonymous id; name and email deliberately absent.",
        "type": "object",
        "required": [
          "person_id",
          "title",
          "business_unit_id",
          "active"
        ],
        "additionalProperties": false,
        "properties": {
          "person_id": {
            "type": "string",
            "pattern": "^p-[a-z0-9]{8}$",
            "examples": [
              "p-4k9d2m1x"
            ]
          },
          "reports_to_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^p-[a-z0-9]{8}$",
            "description": "null only for the top"
          },
          "title": {
            "type": "string",
            "description": "Normalised through the title table"
          },
          "business_unit_id": {
            "type": "string"
          },
          "cost_centre_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "location_country": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[A-Z]{2}$"
          },
          "effective_from": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BusinessUnit": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "name"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "bu-a3jm"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "business_unit",
              "cost_centre"
            ]
          },
          "name": {
            "type": "string"
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "leader_person_id": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Product": {
        "description": "Pack §4 Project and product. One product per service A3JM operates.",
        "type": "object",
        "required": [
          "product_id",
          "name",
          "project_id",
          "business_unit_id",
          "criticality_tier",
          "service_owner_id",
          "product_owner_id",
          "cost_owner_id"
        ],
        "additionalProperties": false,
        "properties": {
          "product_id": {
            "type": "string",
            "examples": [
              "prod-identity"
            ]
          },
          "name": {
            "type": "string",
            "description": "Curated service name (e.g. Identity provider)",
            "never an internal hostname": null
          },
          "project_id": {
            "type": "string"
          },
          "business_unit_id": {
            "type": "string"
          },
          "criticality_tier": {
            "type": "string",
            "enum": [
              "standard",
              "business_critical",
              "mission_critical"
            ]
          },
          "service_owner_id": {
            "type": "string"
          },
          "product_owner_id": {
            "type": "string"
          },
          "cost_owner_id": {
            "type": "string"
          },
          "lifecycle_stage": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "planned",
              "live",
              "sunset",
              "decommissioned",
              null
            ]
          },
          "dr_backup_mode": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "cold",
              "warm",
              "active",
              null
            ]
          }
        }
      },
      "ComponentKind": {
        "type": "string",
        "enum": [
          "cpu",
          "ram",
          "storage",
          "backup_storage",
          "licence",
          "fte",
          "third_party",
          "software"
        ]
      },
      "Component": {
        "description": "Pack §4 Component. Software components carry version and lifecycle dates for the lifecycle enricher.",
        "type": "object",
        "required": [
          "component_id",
          "product_id",
          "kind",
          "name",
          "monthly_cost",
          "capex_or_opex"
        ],
        "additionalProperties": false,
        "properties": {
          "component_id": {
            "type": "string",
            "examples": [
              "sw-reverse-proxy-01"
            ]
          },
          "product_id": {
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/ComponentKind"
          },
          "name": {
            "type": "string",
            "description": "Software product name (e.g. Traefik)",
            "not an instance name": null
          },
          "version": {
            "type": [
              "string",
              "null"
            ],
            "description": "Software only; negotiable whether patch level is included"
          },
          "monthly_cost": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d{1,2})?$",
            "description": "Decimal as string",
            "tenant currency": null
          },
          "capex_or_opex": {
            "type": "string",
            "enum": [
              "capex",
              "opex"
            ]
          },
          "end_of_support": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "end_of_life": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ]
          },
          "contract_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "quantity": {
            "type": [
              "number",
              "null"
            ]
          },
          "unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "host_vm_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "A3JM extension - which VM runs this software component"
          }
        }
      },
      "DataCentre": {
        "type": "object",
        "required": [
          "data_centre_id",
          "region_code",
          "role",
          "backup_mode"
        ],
        "additionalProperties": false,
        "properties": {
          "data_centre_id": {
            "type": "string",
            "examples": [
              "dc-site-a"
            ]
          },
          "region_code": {
            "type": "string",
            "enum": [
              "AP",
              "AM",
              "EU"
            ]
          },
          "role": {
            "type": "string",
            "enum": [
              "primary",
              "secondary"
            ]
          },
          "backup_mode": {
            "type": "string",
            "enum": [
              "cold",
              "warm",
              "active"
            ]
          },
          "capacity_cores": {
            "type": [
              "integer",
              "null"
            ]
          },
          "capacity_memory_gb": {
            "type": [
              "number",
              "null"
            ]
          },
          "site_or_cloud_zone": {
            "type": "string",
            "description": "Class only (on_prem_site",
            "hosted_vps); never an address": null
          }
        }
      },
      "Hypervisor": {
        "type": "object",
        "required": [
          "hypervisor_id",
          "kind",
          "data_centre_id",
          "cores",
          "memory_gb",
          "monthly_asset_cost"
        ],
        "additionalProperties": false,
        "properties": {
          "hypervisor_id": {
            "type": "string",
            "examples": [
              "hv-01"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "esx",
              "proxmox",
              "hyperv",
              "cloud",
              "other"
            ]
          },
          "data_centre_id": {
            "type": "string"
          },
          "cores": {
            "type": "integer"
          },
          "memory_gb": {
            "type": "number"
          },
          "monthly_asset_cost": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d{1,2})?$",
            "description": "Capex amortised monthly; the VM cost deriver's basis"
          },
          "end_of_support": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "end_of_life": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          }
        }
      },
      "Vm": {
        "type": "object",
        "required": [
          "vm_id",
          "hypervisor_id",
          "product_id",
          "cores",
          "memory_gb",
          "disk_gb",
          "os",
          "power_state"
        ],
        "additionalProperties": false,
        "properties": {
          "vm_id": {
            "type": "string",
            "examples": [
              "vm-app-01"
            ],
            "description": "Pseudonym (role class + sequence); never the hypervisor's VM name or id"
          },
          "hypervisor_id": {
            "type": "string"
          },
          "product_id": {
            "type": "string"
          },
          "cores": {
            "type": "integer"
          },
          "memory_gb": {
            "type": "number"
          },
          "disk_gb": {
            "type": "number"
          },
          "os": {
            "type": "string",
            "description": "Distribution and release (e.g. Ubuntu 24.04); kernel build omitted"
          },
          "vm_class": {
            "type": [
              "string",
              "null"
            ]
          },
          "power_state": {
            "type": "string",
            "enum": [
              "running",
              "stopped",
              "suspended"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "backed_up": {
            "type": "boolean",
            "description": "A3JM extension - included in the nightly whole-VM backup job"
          }
        }
      },
      "UsageSample": {
        "type": "object",
        "required": [
          "resource_id",
          "timestamp",
          "cpu_usage_cores",
          "memory_usage_gb"
        ],
        "additionalProperties": false,
        "properties": {
          "resource_id": {
            "type": "string"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "cpu_usage_cores": {
            "type": "number"
          },
          "cpu_usage_cores_max": {
            "type": [
              "number",
              "null"
            ],
            "description": "Interval maximum (A3JM extension)"
          },
          "memory_usage_gb": {
            "type": "number"
          },
          "network_mbps": {
            "type": [
              "number",
              "null"
            ]
          },
          "disk_used_gb": {
            "type": [
              "number",
              "null"
            ],
            "description": "A3JM extension"
          }
        }
      },
      "UsageDaily": {
        "type": "object",
        "required": [
          "resource_id",
          "day",
          "cpu_avg_cores",
          "cpu_p95_cores",
          "memory_avg_gb",
          "memory_p95_gb",
          "sample_count"
        ],
        "additionalProperties": false,
        "properties": {
          "resource_id": {
            "type": "string"
          },
          "day": {
            "type": "string",
            "format": "date"
          },
          "cpu_avg_cores": {
            "type": "number"
          },
          "cpu_p95_cores": {
            "type": "number"
          },
          "memory_avg_gb": {
            "type": "number"
          },
          "memory_p95_gb": {
            "type": "number"
          },
          "sample_count": {
            "type": "integer"
          }
        }
      },
      "Contract": {
        "description": "Pack §4 Finance - Licence or contract / Third party. FTE allocations are not applicable at A3JM.",
        "type": "object",
        "required": [
          "contract_id",
          "vendor",
          "monthly_cost",
          "start"
        ],
        "additionalProperties": false,
        "properties": {
          "contract_id": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "licence",
              "contract",
              "third_party"
            ]
          },
          "vendor": {
            "type": "string"
          },
          "product_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "cost_centre_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "monthly_cost": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d{1,2})?$"
          },
          "start": {
            "type": "string",
            "format": "date"
          },
          "end": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "renewal_notice_days": {
            "type": [
              "integer",
              "null"
            ]
          },
          "quantity": {
            "type": [
              "number",
              "null"
            ]
          },
          "unit": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "code",
          "request_id"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "unauthorized",
              "forbidden_scope",
              "not_found",
              "invalid_parameter",
              "window_too_large",
              "rate_limited",
              "stale_dataset"
            ]
          },
          "request_id": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid key/token",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ForbiddenScope": {
        "description": "Key lacks the required scope",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Unknown resource id",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InvalidParameter": {
        "description": "Bad or oversized window",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
