{
  "openapi": "3.1.0",
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "info": {
    "title": "Galena API",
    "version": "1.2.0",
    "summary": "HTTP API for Galena lead service lines.",
    "description": "Base path /v1. The tenant comes from the token or the API key, never the path. Errors use RFC 9457 problem details. List operations use cursor and limit. POST operations that create a job or a record require Idempotency-Key. Changes to stored resources require If-Match. Long work returns 202 and a Job. Predict returns in the same request for at most 1000 lines. Key scopes: lsl:read, lsl:write, lsl:promote, jobs:read, jobs:write, platform:read, platform:write, audit:read, admin. The admin scope satisfies every operation. The stub app used for contract tests answers 501; the platform service is the deployed API.",
    "contact": {
      "name": "Galena",
      "url": "https://www.craftpine.com/galena"
    },
    "license": {
      "name": "Apache-2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0"
    }
  },
  "servers": [
    {
      "url": "https://galena.craftpine.com"
    }
  ],
  "tags": [
    {
      "name": "Platform",
      "description": "Datasets, jobs, webhooks, keys, audit, connectors, modules, and health."
    },
    {
      "name": "Galena",
      "description": "Lead service line models, scores, predictions, plans, exports, and reports."
    },
    {
      "name": "Webhooks",
      "description": "Signed callbacks the server sends to subscriber URLs."
    }
  ],
  "security": [
    {
      "oidc": []
    },
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/v1/datasets": {
      "post": {
        "operationId": "createDataset",
        "summary": "Start a dataset import.",
        "description": "Accept a dataset description and import it as a job.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "platform:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Start a dataset import.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "dataset.import",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "platform:write"
        ],
        "x-creates": "job",
        "x-async": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DatasetCreate"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "name": "Synthetic city lines",
                    "kind": "service_lines",
                    "format": "csv"
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listDatasets",
        "summary": "List datasets.",
        "description": "List datasets for the tenant, one page at a time.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "platform:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List datasets.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatasetPage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "id": "018bcfe5-6800-7000-8000-0000000000b1",
                          "name": "Synthetic city lines",
                          "kind": "service_lines",
                          "format": "csv",
                          "status": "ready",
                          "created_at": "2026-10-23T16:00:00Z"
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "platform:read"
        ],
        "x-page": true
      }
    },
    "/v1/datasets/{id}/mapping": {
      "post": {
        "operationId": "createDatasetMapping",
        "summary": "Save a dataset field mapping.",
        "description": "Record how source columns map onto canonical fields.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "platform:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Save a dataset field mapping.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatasetMapping"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "dataset_id": "018bcfe5-6800-7000-8000-0000000000b1",
                      "fields": {
                        "year_built": "year_built"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "platform:write"
        ],
        "x-creates": "record",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DatasetMapping"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "dataset_id": "018bcfe5-6800-7000-8000-0000000000b1",
                    "fields": {
                      "year_built": "year_built"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/{id}": {
      "get": {
        "operationId": "getJob",
        "summary": "Read one job.",
        "description": "Return the job status, progress, and result links.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "jobs:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Read one job.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "lsl.model.train",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "jobs:read"
        ]
      }
    },
    "/v1/jobs/{id}:cancel": {
      "post": {
        "operationId": "cancelJob",
        "summary": "Cancel a job.",
        "description": "Ask the worker to stop a queued or running job.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "jobs:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Cancel a job.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "job.cancel",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "jobs:write"
        ],
        "x-creates": "job",
        "x-async": true
      }
    },
    "/v1/webhooks": {
      "post": {
        "operationId": "createWebhook",
        "summary": "Create a webhook.",
        "description": "Create a subscription. The signing secret is returned once. A replay returns the subscription with secret null.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Create a webhook.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              },
              "Cache-Control": {
                "description": "no-store when the body carries a non-null secret. Absent otherwise.",
                "required": false,
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                },
                "example": "no-store"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreated"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "url": "https://example.invalid/hooks/galena",
                      "events": [
                        "job.succeeded"
                      ],
                      "enabled": true,
                      "secret": "example-webhook-secret"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ],
        "x-creates": "record",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "url": "https://example.invalid/hooks/galena",
                    "events": [
                      "job.succeeded"
                    ],
                    "description": "Synthetic receiver"
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listWebhooks",
        "summary": "List webhooks.",
        "description": "List webhook subscriptions. Secrets are not included.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List webhooks.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookPage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "id": "018bcfe5-6800-7000-8000-0000000000aa",
                          "url": "https://example.invalid/hooks/galena",
                          "events": [
                            "job.succeeded"
                          ],
                          "enabled": true,
                          "description": "Synthetic receiver"
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ],
        "x-page": true
      }
    },
    "/v1/webhooks/{id}": {
      "get": {
        "operationId": "getWebhook",
        "summary": "Read one webhook.",
        "description": "Read a webhook subscription without its secret.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Read one webhook.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "url": "https://example.invalid/hooks/galena",
                      "events": [
                        "job.succeeded"
                      ],
                      "enabled": true,
                      "description": "Synthetic receiver"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ]
      },
      "patch": {
        "operationId": "updateWebhook",
        "summary": "Replace a webhook.",
        "description": "Replace the URL, event list, or enabled flag. Send If-Match.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Replace a webhook.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              },
              "Cache-Control": {
                "description": "no-store when the body carries a non-null secret. Absent otherwise.",
                "required": false,
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                },
                "example": "no-store"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookUpdated"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "url": "https://example.invalid/hooks/galena",
                      "events": [
                        "job.succeeded"
                      ],
                      "enabled": true,
                      "description": "Synthetic receiver"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ],
        "x-mutable": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "url": "https://example.invalid/hooks/galena",
                    "events": [
                      "job.succeeded"
                    ],
                    "enabled": true,
                    "description": "Synthetic receiver",
                    "rotate": false
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Delete a webhook.",
        "description": "Delete a webhook subscription. Send If-Match.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "204": {
            "description": "Delete a webhook.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ],
        "x-mutable": true
      }
    },
    "/v1/webhooks/{id}:test": {
      "post": {
        "operationId": "testWebhook",
        "summary": "Send a test delivery.",
        "description": "Enqueue a signed test delivery for this subscription.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Send a test delivery.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "webhook.test",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ],
        "x-creates": "job",
        "x-async": true
      }
    },
    "/v1/webhooks/{id}:replay": {
      "post": {
        "operationId": "replayWebhook",
        "summary": "Replay a dead-lettered delivery.",
        "description": "Enqueue another attempt for one delivery after retries are exhausted.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Replay a dead-lettered delivery.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "webhook.replay",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ],
        "x-creates": "job",
        "x-async": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookReplay"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "delivery_id": "msg_018bcfe5-6800-7000-8000-0000000000aa"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/api-keys": {
      "post": {
        "operationId": "createApiKey",
        "summary": "Create an API key.",
        "description": "Create a scoped key. The secret is returned once and is never logged. A replay returns the key with secret null.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Create an API key.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              },
              "Cache-Control": {
                "description": "no-store when the body carries a non-null secret. Absent otherwise.",
                "required": false,
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                },
                "example": "no-store"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreated"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "name": "Analyst key",
                      "prefix": "cp_example1",
                      "scopes": [
                        "lsl:read"
                      ],
                      "secret": "example-api-key-secret",
                      "created_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ],
        "x-creates": "record",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyCreate"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "name": "Analyst key",
                    "scopes": [
                      "lsl:read"
                    ],
                    "expires_at": null
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listApiKeys",
        "summary": "List API keys.",
        "description": "List key prefixes, scopes, and expiry. Secrets are not included.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List API keys.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyPage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "id": "018bcfe5-6800-7000-8000-0000000000aa",
                          "name": "Analyst key",
                          "prefix": "cp_example1",
                          "scopes": [
                            "lsl:read"
                          ],
                          "expires_at": null,
                          "last_used_at": null,
                          "secret": null,
                          "created_at": "2026-10-23T16:00:00Z"
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ],
        "x-page": true
      }
    },
    "/v1/api-keys/{id}": {
      "get": {
        "operationId": "getApiKey",
        "summary": "Read one API key.",
        "description": "Read a key record without its secret.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Read one API key.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              },
              "Cache-Control": {
                "description": "no-store when the body carries a non-null secret. Absent otherwise.",
                "required": false,
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                },
                "example": "no-store"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKey"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "name": "Analyst key",
                      "prefix": "cp_example1",
                      "scopes": [
                        "lsl:read"
                      ],
                      "expires_at": null,
                      "last_used_at": null,
                      "secret": null,
                      "created_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ]
      },
      "patch": {
        "operationId": "updateApiKey",
        "summary": "Replace an API key record.",
        "description": "Replace scopes or expiry, or rotate the secret. Send If-Match.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Replace an API key record.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              },
              "Cache-Control": {
                "description": "no-store when the body carries a non-null secret. Absent otherwise.",
                "required": false,
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                },
                "example": "no-store"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKey"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "name": "Analyst key",
                      "prefix": "cp_example1",
                      "scopes": [
                        "lsl:read"
                      ],
                      "expires_at": null,
                      "last_used_at": null,
                      "secret": null,
                      "created_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ],
        "x-mutable": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyUpdate"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "name": "Analyst key",
                    "scopes": [
                      "lsl:read"
                    ],
                    "expires_at": null,
                    "rotate": false
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteApiKey",
        "summary": "Revoke an API key.",
        "description": "Revoke a key. Send If-Match.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "204": {
            "description": "Revoke an API key.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "admin"
        ],
        "x-mutable": true
      }
    },
    "/v1/audit-events": {
      "get": {
        "operationId": "listAuditEvents",
        "summary": "List audit events.",
        "description": "List the hash-chained audit log for the tenant.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "audit:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "action",
            "in": "query",
            "required": false,
            "description": "Filter by action name.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9._:-]{1,64}$"
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List audit events.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditEventPage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "id": "018bcfe5-6800-7000-8000-0000000000aa",
                          "occurred_at": "2026-10-23T16:00:00Z",
                          "action": "model.promote",
                          "actor_id": "018bcfe5-6800-7000-8000-000000000001",
                          "hash": "1111111111111111111111111111111111111111111111111111111111111111",
                          "previous_hash": "0000000000000000000000000000000000000000000000000000000000000000"
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "audit:read"
        ],
        "x-page": true
      }
    },
    "/v1/connectors": {
      "post": {
        "operationId": "createConnector",
        "summary": "Create a connector.",
        "description": "Record a connector. Put secrets in the environment, not in config.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "platform:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Create a connector.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Connector"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "name": "Parcel files",
                      "kind": "files",
                      "enabled": true,
                      "config": {
                        "base_url": "https://example.invalid/files"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "platform:write"
        ],
        "x-creates": "record",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConnectorCreate"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "name": "Parcel files",
                    "kind": "files",
                    "enabled": true,
                    "config": {
                      "base_url": "https://example.invalid/files"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listConnectors",
        "summary": "List connectors.",
        "description": "List connector records for the tenant.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "platform:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List connectors.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectorPage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "id": "018bcfe5-6800-7000-8000-0000000000aa",
                          "name": "Parcel files",
                          "kind": "files",
                          "enabled": true,
                          "config": {
                            "base_url": "https://example.invalid/files"
                          }
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "platform:read"
        ],
        "x-page": true
      }
    },
    "/v1/connectors/{id}": {
      "get": {
        "operationId": "getConnector",
        "summary": "Read one connector.",
        "description": "Read a connector record.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "platform:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Read one connector.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Connector"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "name": "Parcel files",
                      "kind": "files",
                      "enabled": true,
                      "config": {
                        "base_url": "https://example.invalid/files"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "platform:read"
        ]
      },
      "patch": {
        "operationId": "updateConnector",
        "summary": "Replace a connector.",
        "description": "Replace connector settings. Send If-Match.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "platform:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Replace a connector.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Connector"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "name": "Parcel files",
                      "kind": "files",
                      "enabled": true,
                      "config": {
                        "base_url": "https://example.invalid/files"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "platform:write"
        ],
        "x-mutable": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConnectorUpdate"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "name": "Parcel files",
                    "enabled": true,
                    "config": {
                      "base_url": "https://example.invalid/files"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteConnector",
        "summary": "Delete a connector.",
        "description": "Delete a connector record. Send If-Match.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "platform:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "204": {
            "description": "Delete a connector.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "platform:write"
        ],
        "x-mutable": true
      }
    },
    "/v1/connectors/{id}:sync": {
      "post": {
        "operationId": "syncConnector",
        "summary": "Sync a connector.",
        "description": "Enqueue a sync for this connector.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "platform:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Sync a connector.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "connector.sync",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "platform:write"
        ],
        "x-creates": "job",
        "x-async": true
      }
    },
    "/v1/modules": {
      "get": {
        "operationId": "listModules",
        "summary": "List modules.",
        "description": "List installed product modules and whether each is enabled.",
        "tags": [
          "Platform"
        ],
        "security": [
          {
            "oidc": [
              "platform:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List modules.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModulePage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "name": "galena",
                          "version": "1.0.0",
                          "enabled": true
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "platform:read"
        ],
        "x-page": true
      }
    },
    "/v1/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Process health.",
        "description": "Report that the process is up. This operation does not require a credential.",
        "tags": [
          "Platform"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Process health.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "status": "ok"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        }
      }
    },
    "/v1/version": {
      "get": {
        "operationId": "getVersion",
        "summary": "API version.",
        "description": "Report the contract version. This operation does not require a credential.",
        "tags": [
          "Platform"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "API version.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Version"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "api": "v1",
                      "version": "1.0.0"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        }
      }
    },
    "/v1/lsl/models": {
      "post": {
        "operationId": "createModel",
        "summary": "Train a model.",
        "description": "Enqueue training for one snapshot. The model version is a job result.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Train a model.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "lsl.model.train",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:write"
        ],
        "x-creates": "job",
        "x-async": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrainModelRequest"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "algorithm": "lightgbm",
                    "training_snapshot_id": "018bcfe5-6800-7000-8000-000000000008",
                    "params": {
                      "seed": 1
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listModels",
        "summary": "List model versions.",
        "description": "List model versions and their lineage.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List model versions.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelVersionPage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "algorithm": "rules",
                          "code_commit": "0000000000000000000000000000000000000006",
                          "eval_report_id": "018bcfe5-6800-7000-8000-000000000008",
                          "feature_set_hash": "0000000000000000000000000000000000000000000000000000000000000006",
                          "id": "018bcfe5-6800-7000-8000-000000000006",
                          "params": {
                            "seed": 6
                          },
                          "promoted_at": null,
                          "promoted_by": null,
                          "schema_version": "2.1.0",
                          "status": "CANDIDATE",
                          "training_snapshot_id": "018bcfe5-6800-7000-8000-000000000007"
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:read"
        ],
        "x-page": true
      }
    },
    "/v1/lsl/models/{id}:promote": {
      "post": {
        "operationId": "promoteModel",
        "summary": "Promote a model.",
        "description": "Record an approver promotion. Requires the lsl:promote scope.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:promote"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Promote a model.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelVersion"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "algorithm": "rules",
                      "code_commit": "0000000000000000000000000000000000000006",
                      "eval_report_id": "018bcfe5-6800-7000-8000-000000000008",
                      "feature_set_hash": "0000000000000000000000000000000000000000000000000000000000000006",
                      "id": "018bcfe5-6800-7000-8000-000000000006",
                      "params": {
                        "seed": 6
                      },
                      "promoted_at": "2026-10-23T16:00:00Z",
                      "promoted_by": "018bcfe5-6800-7000-8000-000000000001",
                      "schema_version": "2.1.0",
                      "status": "PROMOTED",
                      "training_snapshot_id": "018bcfe5-6800-7000-8000-000000000007"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:promote"
        ],
        "x-creates": "record",
        "x-mutable": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PromoteModelRequest"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "note": "promote candidate"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/lsl/scores": {
      "post": {
        "operationId": "scoreLines",
        "summary": "Score a snapshot.",
        "description": "Enqueue batch scoring for a snapshot.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Score a snapshot.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "lsl.score",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:write"
        ],
        "x-creates": "job",
        "x-async": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScoreRequest"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "model_version_id": "018bcfe5-6800-7000-8000-000000000007",
                    "data_snapshot_id": "018bcfe5-6800-7000-8000-000000000008"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/lsl/predict": {
      "post": {
        "operationId": "predictLines",
        "summary": "Predict up to 1000 lines.",
        "description": "Score up to 1000 service lines in this request and store the predictions.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Predict up to 1000 lines.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PredictResponse"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "model_version_id": "018bcfe5-6800-7000-8000-000000000007",
                      "predictions": [
                        {
                          "abstain": false,
                          "alpha": 0.05,
                          "conformal_set": [
                            "NON_LEAD"
                          ],
                          "data_snapshot_id": "018bcfe5-6800-7000-8000-000000000008",
                          "model_version_id": "018bcfe5-6800-7000-8000-000000000007",
                          "p_grr": 0.1,
                          "p_lead": 0.2,
                          "p_non_lead": 0.7,
                          "prediction_id": "018bcfe5-6800-7000-8000-000000000005",
                          "schema_version": "2.1.0",
                          "service_line_id": "018bcfe5-6800-7000-8000-000000000006",
                          "top_factors": [
                            {
                              "contribution": -0.1,
                              "feature": "year_built"
                            }
                          ]
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:write"
        ],
        "x-creates": "record",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PredictRequest"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "model_version_id": "018bcfe5-6800-7000-8000-000000000007",
                    "service_line_ids": [
                      "018bcfe5-6800-7000-8000-000000000006"
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/lsl/predictions": {
      "get": {
        "operationId": "listPredictions",
        "summary": "List predictions.",
        "description": "List stored predictions.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "model_version_id",
            "in": "query",
            "required": false,
            "description": "Filter by model version.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List predictions.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PredictionPage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "abstain": false,
                          "alpha": 0.05,
                          "conformal_set": [
                            "NON_LEAD"
                          ],
                          "data_snapshot_id": "018bcfe5-6800-7000-8000-000000000008",
                          "model_version_id": "018bcfe5-6800-7000-8000-000000000007",
                          "p_grr": 0.1,
                          "p_lead": 0.2,
                          "p_non_lead": 0.7,
                          "prediction_id": "018bcfe5-6800-7000-8000-000000000005",
                          "schema_version": "2.1.0",
                          "service_line_id": "018bcfe5-6800-7000-8000-000000000006",
                          "top_factors": [
                            {
                              "contribution": -0.1,
                              "feature": "year_built"
                            }
                          ]
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:read"
        ],
        "x-page": true
      }
    },
    "/v1/lsl/predictions/{service_line_id}": {
      "get": {
        "operationId": "getPrediction",
        "summary": "Read the prediction for one service line.",
        "description": "Return the current prediction for one service line.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "service_line_id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the service line.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Read the prediction for one service line.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Prediction"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "abstain": false,
                      "alpha": 0.05,
                      "conformal_set": [
                        "NON_LEAD"
                      ],
                      "data_snapshot_id": "018bcfe5-6800-7000-8000-000000000008",
                      "model_version_id": "018bcfe5-6800-7000-8000-000000000007",
                      "p_grr": 0.1,
                      "p_lead": 0.2,
                      "p_non_lead": 0.7,
                      "prediction_id": "018bcfe5-6800-7000-8000-000000000005",
                      "schema_version": "2.1.0",
                      "service_line_id": "018bcfe5-6800-7000-8000-000000000006",
                      "top_factors": [
                        {
                          "contribution": -0.1,
                          "feature": "year_built"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:read"
        ]
      }
    },
    "/v1/lsl/verifications": {
      "post": {
        "operationId": "createVerification",
        "summary": "Record a verification.",
        "description": "Store one field verification, including its selection record.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Record a verification.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verification"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "method": "POTHOLE",
                      "notes_text": "synthetic field note",
                      "observed_at": "2024-06-15T12:00:00Z",
                      "observed_material": "COPPER",
                      "photo_refs": [
                        "synthetic/photos/3.bin"
                      ],
                      "schema_version": "2.1.0",
                      "selection": {
                        "batch_id": null,
                        "design": "CUSTOMER_REQUEST",
                        "inclusion_probability": null
                      },
                      "service_line_id": "018bcfe5-6800-7000-8000-000000000004",
                      "side": "UTILITY",
                      "verification_detail": null,
                      "verification_id": "018bcfe5-6800-7000-8000-000000000003"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:write"
        ],
        "x-creates": "record",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Verification"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "method": "POTHOLE",
                    "notes_text": "synthetic field note",
                    "observed_at": "2024-06-15T12:00:00Z",
                    "observed_material": "COPPER",
                    "photo_refs": [
                      "synthetic/photos/3.bin"
                    ],
                    "schema_version": "2.1.0",
                    "selection": {
                      "batch_id": null,
                      "design": "CUSTOMER_REQUEST",
                      "inclusion_probability": null
                    },
                    "service_line_id": "018bcfe5-6800-7000-8000-000000000004",
                    "side": "UTILITY",
                    "verification_detail": null,
                    "verification_id": "018bcfe5-6800-7000-8000-000000000003"
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listVerifications",
        "summary": "List verifications.",
        "description": "List field verifications.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List verifications.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationPage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "method": "POTHOLE",
                          "notes_text": "synthetic field note",
                          "observed_at": "2024-06-15T12:00:00Z",
                          "observed_material": "COPPER",
                          "photo_refs": [
                            "synthetic/photos/3.bin"
                          ],
                          "schema_version": "2.1.0",
                          "selection": {
                            "batch_id": null,
                            "design": "CUSTOMER_REQUEST",
                            "inclusion_probability": null
                          },
                          "service_line_id": "018bcfe5-6800-7000-8000-000000000004",
                          "side": "UTILITY",
                          "verification_detail": null,
                          "verification_id": "018bcfe5-6800-7000-8000-000000000003"
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:read"
        ],
        "x-page": true
      }
    },
    "/v1/lsl/rollups": {
      "get": {
        "operationId": "listRollups",
        "summary": "List lead-count rollups.",
        "description": "List estimates for one geography level.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "level",
            "in": "query",
            "required": true,
            "description": "Geography level.",
            "schema": {
              "type": "string",
              "enum": [
                "SYSTEM",
                "TRACT",
                "BLOCK",
                "NEIGHBOURHOOD",
                "H3"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List lead-count rollups.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimatePage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "estimate_id": "018bcfe5-6800-7000-8000-000000000008",
                          "expected_lead": 3.5,
                          "level": 0.9,
                          "lower": 1.0,
                          "method": "MODEL_BASED",
                          "n_unknown": 10,
                          "n_verified": 4,
                          "schema_version": "2.1.0",
                          "scope": "SYSTEM",
                          "scope_key": null,
                          "upper": 6.0
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:read"
        ],
        "x-page": true
      }
    },
    "/v1/lsl/estimates": {
      "get": {
        "operationId": "listEstimates",
        "summary": "List lead-count estimates.",
        "description": "List estimates with their intervals.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "description": "Filter by geography level.",
            "schema": {
              "type": "string",
              "enum": [
                "SYSTEM",
                "TRACT",
                "BLOCK",
                "NEIGHBOURHOOD",
                "H3"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List lead-count estimates.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimatePage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "estimate_id": "018bcfe5-6800-7000-8000-000000000008",
                          "expected_lead": 3.5,
                          "level": 0.9,
                          "lower": 1.0,
                          "method": "MODEL_BASED",
                          "n_unknown": 10,
                          "n_verified": 4,
                          "schema_version": "2.1.0",
                          "scope": "SYSTEM",
                          "scope_key": null,
                          "upper": 6.0
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:read"
        ],
        "x-page": true
      }
    },
    "/v1/lsl/inspection-plans": {
      "post": {
        "operationId": "createInspectionPlan",
        "summary": "Build an inspection plan.",
        "description": "Enqueue an inspection plan for a budget and a mode.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Build an inspection plan.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "lsl.inspection_plan",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:write"
        ],
        "x-creates": "job",
        "x-async": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InspectionPlanRequest"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "mode": "REPRESENTATIVE",
                    "budget_n": 10,
                    "probability_share": 0.2,
                    "seed": 1
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listInspectionPlans",
        "summary": "List inspection plans.",
        "description": "Return stored inspection plans.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List inspection plans.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InspectionPlanPage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "budget_n": 1,
                          "items": [
                            {
                              "expected_value": 0.3,
                              "inclusion_probability": 0.2,
                              "rank": 1,
                              "reason_code": "LEAD_LIKELY",
                              "service_line_id": "018bcfe5-6800-7000-8000-000000000008"
                            }
                          ],
                          "mode": "MIXED",
                          "plan_id": "018bcfe5-6800-7000-8000-000000000007",
                          "probability_share": 0.2,
                          "schema_version": "2.1.0",
                          "seed": 7
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:read"
        ],
        "x-page": true
      }
    },
    "/v1/lsl/validation-plans": {
      "post": {
        "operationId": "createValidationPlan",
        "summary": "Build a validation plan.",
        "description": "Enqueue a validation sample.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Build a validation plan.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "lsl.validation_plan",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:write"
        ],
        "x-creates": "job",
        "x-async": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValidationPlanRequest"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "mode": "LCRI_VALIDATION",
                    "budget_n": 10,
                    "seed": 1
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/lsl/validation-plans/{id}/results": {
      "post": {
        "operationId": "submitValidationResults",
        "summary": "Submit validation results.",
        "description": "Store verification results for one validation plan.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Submit validation results.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationResults"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "accepted": 1
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:write"
        ],
        "x-creates": "record",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValidationResultsRequest"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "verifications": [
                      {
                        "method": "POTHOLE",
                        "notes_text": "synthetic field note",
                        "observed_at": "2024-06-15T12:00:00Z",
                        "observed_material": "COPPER",
                        "photo_refs": [
                          "synthetic/photos/3.bin"
                        ],
                        "schema_version": "2.1.0",
                        "selection": {
                          "batch_id": null,
                          "design": "CUSTOMER_REQUEST",
                          "inclusion_probability": null
                        },
                        "service_line_id": "018bcfe5-6800-7000-8000-000000000004",
                        "side": "UTILITY",
                        "verification_detail": null,
                        "verification_id": "018bcfe5-6800-7000-8000-000000000003"
                      }
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/lsl/validation-designs": {
      "post": {
        "operationId": "designValidationSample",
        "summary": "Design a validation sample.",
        "description": "Return a sample and a regulator pack for one inventory file. No credential is required. Nothing is stored.",
        "tags": [
          "Galena"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Design a validation sample.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationDesign"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "design": {
                        "budget_curve": null,
                        "budget_n": 0,
                        "effective_ban": "1988-06-19",
                        "exclusions": [
                          {
                            "count": 1,
                            "reason": "class is not non-lead"
                          },
                          {
                            "count": 0,
                            "reason": "install year is after the ban"
                          }
                        ],
                        "federal_ban": "1988-06-19",
                        "git_sha": "0000000000000000000000000000000000000000",
                        "inclusion_summary": "The sample file is sample.csv. Each chosen line has inclusion probability 0.250000000000. In the pool those probabilities sum to 2.",
                        "inspection_methods": [
                          "VISUAL_1PT",
                          "VISUAL_2PT",
                          "POTHOLE",
                          "EXCAVATION",
                          "CCTV",
                          "CUSTOMER_PHOTO",
                          "RECORD",
                          "XRF",
                          "MAGNET_SCRATCH"
                        ],
                        "inventory_version": "test",
                        "missing_columns": [],
                        "mode": "LCRI_VALIDATION",
                        "package_version": "0.0.0",
                        "pool_definition": "The pool is every line whose class is non-lead.",
                        "pool_size": 8,
                        "probability_share": "0.2",
                        "reproduce_command": "uv run galena validate-plan --inventory INVENTORY.csv --mode LCRI_VALIDATION --budget 0 --share 0.2 --seed 7 --inventory-version test --out OUT",
                        "row_count": 10,
                        "sample_size": 2,
                        "schedule_end_year": 2034,
                        "schedule_start_year": 2025,
                        "seed": 7,
                        "state_ban": null,
                        "strata": [
                          {
                            "allocation": 2,
                            "inclusion_sum": "2.000000",
                            "population": 8,
                            "stratum": "non-lead validation pool"
                          }
                        ],
                        "table_row": "under 1500, sample 2, one fifth rule"
                      },
                      "sample_csv": "line_id,hex,stratum,inclusion_probability,pick_order,schedule_year\nA1,882af63191fffff,non-lead validation pool,0.250000000000,1,2025\nA2,882af63193fffff,non-lead validation pool,0.250000000000,2,2026\n",
                      "pack_html": "<p>Validation sample pack. The pool has 8 lines. The sample has 2 lines.</p>\n"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValidationDesignRequest"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "mode": "LCRI_VALIDATION",
                    "budget_n": 0,
                    "probability_share": 0.2,
                    "seed": 1,
                    "inventory_version": "test",
                    "state_ban_year": null,
                    "inventory_csv": "line_id,material_class,install_year,hex\nA1,NON_LEAD,1950,882af63191fffff\nA2,NON_LEAD,1960,882af63193fffff\nA3,NON_LEAD,1970,882af63195fffff\nA4,NON_LEAD,1980,882af63197fffff\nA5,NON_LEAD,1988,882af63199fffff\nA6,LEAD,1950,882af6319bfffff\n"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/lsl/exports": {
      "post": {
        "operationId": "createExport",
        "summary": "Build an export.",
        "description": "Enqueue an inventory export in one of the supported formats.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Build an export.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "lsl.export",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:write"
        ],
        "x-creates": "job",
        "x-async": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExportRequest"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "format": "csv",
                    "model_version_id": "018bcfe5-6800-7000-8000-000000000007"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/lsl/reports": {
      "post": {
        "operationId": "createReport",
        "summary": "Build a model report.",
        "description": "Enqueue a model report.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:write"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Build a model report.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "status": "queued",
                      "kind": "lsl.report",
                      "progress": 0,
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ],
                      "error": null,
                      "created_at": "2026-10-23T16:00:00Z",
                      "updated_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:write"
        ],
        "x-creates": "job",
        "x-async": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportRequest"
              },
              "examples": {
                "sample": {
                  "summary": "Sample",
                  "value": {
                    "kind": "model",
                    "model_version_id": "018bcfe5-6800-7000-8000-000000000007"
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listReports",
        "summary": "List reports.",
        "description": "List model reports and their files.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "List reports.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportPage"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "data": [
                        {
                          "id": "018bcfe5-6800-7000-8000-0000000000aa",
                          "kind": "model",
                          "status": "queued",
                          "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                          "href": null
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:read"
        ],
        "x-page": true
      }
    },
    "/v1/lsl/evaluations/{id}": {
      "get": {
        "operationId": "getEvaluation",
        "summary": "Read an evaluation report.",
        "description": "Return one evaluation report.",
        "tags": [
          "Galena"
        ],
        "security": [
          {
            "oidc": [
              "lsl:read"
            ]
          },
          {
            "oidc": [
              "admin"
            ]
          },
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUIDv7 of the resource.",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Read an evaluation report.",
            "headers": {
              "RateLimit-Policy": {
                "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";q=60;w=60"
              },
              "RateLimit": {
                "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"default\";r=59;t=60"
              },
              "ETag": {
                "description": "RFC 9110 entity tag. Send it back as If-Match.",
                "required": true,
                "schema": {
                  "type": "string"
                },
                "example": "\"example-etag\""
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvalReport"
                },
                "examples": {
                  "sample": {
                    "summary": "Sample",
                    "value": {
                      "bias_diagnostics": {
                        "auc": 0.5
                      },
                      "calibration": {
                        "ece": 0.02
                      },
                      "conformal": {
                        "alpha": 0.05
                      },
                      "dataset_card": {
                        "label": "synthetic"
                      },
                      "drift": {
                        "psi": 0.0
                      },
                      "equity": {
                        "status": "synthetic"
                      },
                      "gate_decision": {
                        "decision": "PASS",
                        "reasons": []
                      },
                      "leakage": {
                        "canary": true
                      },
                      "metrics": [
                        {
                          "group_key": null,
                          "metrics": [
                            {
                              "estimate": 0.4,
                              "interval": {
                                "level": 0.95,
                                "lower": 0.2,
                                "upper": 0.6
                              },
                              "name": "log_loss"
                            }
                          ],
                          "scope": "OVERALL"
                        }
                      ],
                      "model_card": {
                        "algorithm": "rules"
                      },
                      "red_team": {
                        "passed": true
                      },
                      "report_id": "018bcfe5-6800-7000-8000-000000000009",
                      "schema_version": "2.1.0",
                      "seeds": [
                        9
                      ],
                      "split_strategy": "spatial_block",
                      "versions": {
                        "eval": "0.0.0"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        },
        "x-required-scopes": [
          "lsl:read"
        ]
      }
    }
  },
  "webhooks": {
    "job.succeeded": {
      "post": {
        "operationId": "webhookJobSucceeded",
        "summary": "Deliver job.succeeded.",
        "description": "The server POSTs this body to the subscriber. Standard Webhooks headers authenticate the delivery. Delivery is at least once, with backoff for 24 hours, then dead-letter.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobSucceededEvent"
              },
              "examples": {
                "sample": {
                  "summary": "job.succeeded",
                  "value": {
                    "type": "job.succeeded",
                    "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
                    "time": "2026-10-23T16:00:00Z",
                    "data": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "kind": "lsl.model.train",
                      "status": "succeeded",
                      "result_links": [
                        {
                          "rel": "self",
                          "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "The receiver accepted the event."
          },
          "410": {
            "description": "The receiver is gone. Deliveries to this URL stop."
          }
        }
      }
    },
    "job.failed": {
      "post": {
        "operationId": "webhookJobFailed",
        "summary": "Deliver job.failed.",
        "description": "The server POSTs this body to the subscriber. Standard Webhooks headers authenticate the delivery. Delivery is at least once, with backoff for 24 hours, then dead-letter.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobFailedEvent"
              },
              "examples": {
                "sample": {
                  "summary": "job.failed",
                  "value": {
                    "type": "job.failed",
                    "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
                    "time": "2026-10-23T16:00:00Z",
                    "data": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "kind": "lsl.model.train",
                      "status": "failed",
                      "error": {
                        "type": "https://example.invalid/problems/internal",
                        "title": "Internal Server Error",
                        "status": 500,
                        "detail": "The job failed. The detail is a synthetic fixture."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "The receiver accepted the event."
          },
          "410": {
            "description": "The receiver is gone. Deliveries to this URL stop."
          }
        }
      }
    },
    "model.candidate_ready": {
      "post": {
        "operationId": "webhookModelCandidateReady",
        "summary": "Deliver model.candidate_ready.",
        "description": "The server POSTs this body to the subscriber. Standard Webhooks headers authenticate the delivery. Delivery is at least once, with backoff for 24 hours, then dead-letter.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ModelCandidateReadyEvent"
              },
              "examples": {
                "sample": {
                  "summary": "model.candidate_ready",
                  "value": {
                    "type": "model.candidate_ready",
                    "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
                    "time": "2026-10-23T16:00:00Z",
                    "data": {
                      "model_version_id": "018bcfe5-6800-7000-8000-000000000006",
                      "eval_report_id": "018bcfe5-6800-7000-8000-000000000008",
                      "status": "CANDIDATE"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "The receiver accepted the event."
          },
          "410": {
            "description": "The receiver is gone. Deliveries to this URL stop."
          }
        }
      }
    },
    "model.promoted": {
      "post": {
        "operationId": "webhookModelPromoted",
        "summary": "Deliver model.promoted.",
        "description": "The server POSTs this body to the subscriber. Standard Webhooks headers authenticate the delivery. Delivery is at least once, with backoff for 24 hours, then dead-letter.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ModelPromotedEvent"
              },
              "examples": {
                "sample": {
                  "summary": "model.promoted",
                  "value": {
                    "type": "model.promoted",
                    "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
                    "time": "2026-10-23T16:00:00Z",
                    "data": {
                      "model_version_id": "018bcfe5-6800-7000-8000-000000000006",
                      "promoted_by": "018bcfe5-6800-7000-8000-000000000001",
                      "promoted_at": "2026-10-23T16:00:00Z"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "The receiver accepted the event."
          },
          "410": {
            "description": "The receiver is gone. Deliveries to this URL stop."
          }
        }
      }
    },
    "predictions.updated": {
      "post": {
        "operationId": "webhookPredictionsUpdated",
        "summary": "Deliver predictions.updated.",
        "description": "The server POSTs this body to the subscriber. Standard Webhooks headers authenticate the delivery. Delivery is at least once, with backoff for 24 hours, then dead-letter.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PredictionsUpdatedEvent"
              },
              "examples": {
                "sample": {
                  "summary": "predictions.updated",
                  "value": {
                    "type": "predictions.updated",
                    "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
                    "time": "2026-10-23T16:00:00Z",
                    "data": {
                      "model_version_id": "018bcfe5-6800-7000-8000-000000000007",
                      "data_snapshot_id": "018bcfe5-6800-7000-8000-000000000008",
                      "count": 1
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "The receiver accepted the event."
          },
          "410": {
            "description": "The receiver is gone. Deliveries to this URL stop."
          }
        }
      }
    },
    "inspection_plan.ready": {
      "post": {
        "operationId": "webhookInspectionPlanReady",
        "summary": "Deliver inspection_plan.ready.",
        "description": "The server POSTs this body to the subscriber. Standard Webhooks headers authenticate the delivery. Delivery is at least once, with backoff for 24 hours, then dead-letter.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InspectionPlanReadyEvent"
              },
              "examples": {
                "sample": {
                  "summary": "inspection_plan.ready",
                  "value": {
                    "type": "inspection_plan.ready",
                    "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
                    "time": "2026-10-23T16:00:00Z",
                    "data": {
                      "plan": {
                        "budget_n": 1,
                        "items": [
                          {
                            "expected_value": 0.3,
                            "inclusion_probability": 0.2,
                            "rank": 1,
                            "reason_code": "LEAD_LIKELY",
                            "service_line_id": "018bcfe5-6800-7000-8000-000000000008"
                          }
                        ],
                        "mode": "MIXED",
                        "plan_id": "018bcfe5-6800-7000-8000-000000000007",
                        "probability_share": 0.2,
                        "schema_version": "2.1.0",
                        "seed": 7
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "The receiver accepted the event."
          },
          "410": {
            "description": "The receiver is gone. Deliveries to this URL stop."
          }
        }
      }
    },
    "verification.contradicts_model": {
      "post": {
        "operationId": "webhookVerificationContradictsModel",
        "summary": "Deliver verification.contradicts_model.",
        "description": "The server POSTs this body to the subscriber. Standard Webhooks headers authenticate the delivery. Delivery is at least once, with backoff for 24 hours, then dead-letter.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerificationContradictsModelEvent"
              },
              "examples": {
                "sample": {
                  "summary": "verification.contradicts_model",
                  "value": {
                    "type": "verification.contradicts_model",
                    "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
                    "time": "2026-10-23T16:00:00Z",
                    "data": {
                      "verification": {
                        "method": "POTHOLE",
                        "notes_text": "synthetic field note",
                        "observed_at": "2024-06-15T12:00:00Z",
                        "observed_material": "COPPER",
                        "photo_refs": [
                          "synthetic/photos/3.bin"
                        ],
                        "schema_version": "2.1.0",
                        "selection": {
                          "batch_id": null,
                          "design": "CUSTOMER_REQUEST",
                          "inclusion_probability": null
                        },
                        "service_line_id": "018bcfe5-6800-7000-8000-000000000004",
                        "side": "UTILITY",
                        "verification_detail": null,
                        "verification_id": "018bcfe5-6800-7000-8000-000000000003"
                      },
                      "prediction": {
                        "abstain": false,
                        "alpha": 0.05,
                        "conformal_set": [
                          "LEAD"
                        ],
                        "data_snapshot_id": "018bcfe5-6800-7000-8000-000000000008",
                        "model_version_id": "018bcfe5-6800-7000-8000-000000000007",
                        "p_grr": 0.1,
                        "p_lead": 0.8,
                        "p_non_lead": 0.1,
                        "prediction_id": "018bcfe5-6800-7000-8000-000000000005",
                        "schema_version": "2.1.0",
                        "service_line_id": "018bcfe5-6800-7000-8000-000000000006",
                        "top_factors": [
                          {
                            "contribution": -0.1,
                            "feature": "year_built"
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "The receiver accepted the event."
          },
          "410": {
            "description": "The receiver is gone. Deliveries to this URL stop."
          }
        }
      }
    },
    "export.ready": {
      "post": {
        "operationId": "webhookExportReady",
        "summary": "Deliver export.ready.",
        "description": "The server POSTs this body to the subscriber. Standard Webhooks headers authenticate the delivery. Delivery is at least once, with backoff for 24 hours, then dead-letter.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExportReadyEvent"
              },
              "examples": {
                "sample": {
                  "summary": "export.ready",
                  "value": {
                    "type": "export.ready",
                    "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
                    "time": "2026-10-23T16:00:00Z",
                    "data": {
                      "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
                      "format": "csv",
                      "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "The receiver accepted the event."
          },
          "410": {
            "description": "The receiver is gone. Deliveries to this URL stop."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. Additional members are allowed.",
        "additionalProperties": true,
        "required": [
          "type",
          "title",
          "status"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri-reference"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string",
            "format": "uri-reference"
          }
        }
      },
      "ResultLink": {
        "type": "object",
        "additionalProperties": false,
        "description": "A link to a job result.",
        "properties": {
          "rel": {
            "type": "string",
            "pattern": "^[a-z0-9._:-]{1,32}$"
          },
          "href": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "rel",
          "href"
        ]
      },
      "Job": {
        "type": "object",
        "additionalProperties": false,
        "description": "Asynchronous work. Poll GET /v1/jobs/{id} until status is terminal.",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the job."
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "succeeded",
              "failed",
              "cancelled"
            ],
            "description": "Job lifecycle status."
          },
          "kind": {
            "type": "string",
            "pattern": "^[a-z0-9._:-]{1,64}$",
            "description": "Job kind, such as lsl.model.train."
          },
          "progress": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "Fraction complete, from 0 to 1."
          },
          "result_links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResultLink"
            }
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Problem"
              },
              {
                "type": "null"
              }
            ],
            "description": "Present when status is failed."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "job_id",
          "status",
          "kind",
          "progress",
          "result_links",
          "error",
          "created_at",
          "updated_at"
        ]
      },
      "DatasetCreate": {
        "type": "object",
        "additionalProperties": false,
        "description": "A dataset to import. The import itself is a job.",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[A-Za-z0-9 ._-]{1,120}$",
            "description": "Display name."
          },
          "kind": {
            "type": "string",
            "enum": [
              "service_lines",
              "parcels",
              "observations",
              "rainfall",
              "network"
            ]
          },
          "format": {
            "type": "string",
            "enum": [
              "csv",
              "geojson",
              "gpkg",
              "parquet"
            ]
          }
        },
        "required": [
          "name",
          "kind"
        ]
      },
      "Dataset": {
        "type": "object",
        "additionalProperties": false,
        "description": "A stored dataset.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the dataset."
          },
          "name": {
            "type": "string",
            "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
          },
          "kind": {
            "type": "string",
            "enum": [
              "service_lines",
              "parcels",
              "observations",
              "rainfall",
              "network"
            ]
          },
          "format": {
            "type": "string",
            "enum": [
              "csv",
              "geojson",
              "gpkg",
              "parquet"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "ready",
              "failed"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "kind",
          "status",
          "created_at"
        ]
      },
      "DatasetMapping": {
        "type": "object",
        "additionalProperties": false,
        "description": "Column mapping for one dataset. dataset_id matches the path id.",
        "properties": {
          "dataset_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the dataset."
          },
          "fields": {
            "type": "object",
            "description": "Source column name to canonical field name.",
            "additionalProperties": {
              "type": "string",
              "maxLength": 200
            }
          }
        },
        "required": [
          "dataset_id",
          "fields"
        ]
      },
      "WebhookCreate": {
        "type": "object",
        "additionalProperties": false,
        "description": "A new webhook subscription.",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "job.succeeded",
                "job.failed",
                "model.candidate_ready",
                "model.promoted",
                "predictions.updated",
                "inspection_plan.ready",
                "verification.contradicts_model",
                "wq.alert.opened",
                "wq.alert.resolved",
                "wq.compliance.exceedance",
                "sewer.overflow_risk.raised",
                "sewer.dry_weather_overflow.detected",
                "export.ready"
              ]
            },
            "description": "Event types this subscription receives."
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Short label. No personal data."
          }
        },
        "required": [
          "url",
          "events"
        ]
      },
      "Webhook": {
        "type": "object",
        "additionalProperties": false,
        "description": "A webhook subscription. The signing secret is not returned here.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the webhook."
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "job.succeeded",
                "job.failed",
                "model.candidate_ready",
                "model.promoted",
                "predictions.updated",
                "inspection_plan.ready",
                "verification.contradicts_model",
                "wq.alert.opened",
                "wq.alert.resolved",
                "wq.compliance.exceedance",
                "sewer.overflow_risk.raised",
                "sewer.dry_weather_overflow.detected",
                "export.ready"
              ]
            },
            "description": "Event types this subscription receives."
          },
          "enabled": {
            "type": "boolean"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Short label."
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "enabled"
        ]
      },
      "WebhookCreated": {
        "type": "object",
        "additionalProperties": false,
        "description": "The create response. secret is shown once.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the webhook."
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "job.succeeded",
                "job.failed",
                "model.candidate_ready",
                "model.promoted",
                "predictions.updated",
                "inspection_plan.ready",
                "verification.contradicts_model",
                "wq.alert.opened",
                "wq.alert.resolved",
                "wq.compliance.exceedance",
                "sewer.overflow_risk.raised",
                "sewer.dry_weather_overflow.detected",
                "export.ready"
              ]
            },
            "description": "Event types this subscription receives."
          },
          "enabled": {
            "type": "boolean"
          },
          "secret": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 8,
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "description": "Signing secret. Present on the first response only. Not a live credential."
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "enabled",
          "secret"
        ]
      },
      "WebhookUpdate": {
        "type": "object",
        "additionalProperties": false,
        "description": "Replacement webhook settings. With rotate true, the response shows the new secret.",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "job.succeeded",
                "job.failed",
                "model.candidate_ready",
                "model.promoted",
                "predictions.updated",
                "inspection_plan.ready",
                "verification.contradicts_model",
                "wq.alert.opened",
                "wq.alert.resolved",
                "wq.compliance.exceedance",
                "sewer.overflow_risk.raised",
                "sewer.dry_weather_overflow.detected",
                "export.ready"
              ]
            },
            "description": "Event types this subscription receives."
          },
          "enabled": {
            "type": "boolean"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Short label."
          },
          "rotate": {
            "type": "boolean",
            "description": "When true, rotate the signing secret. The update response returns the new secret once, in its secret field."
          }
        },
        "required": [
          "url",
          "events",
          "enabled"
        ]
      },
      "WebhookUpdated": {
        "type": "object",
        "additionalProperties": false,
        "description": "The update response. secret is present only after a rotation, and is shown once.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the webhook."
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "job.succeeded",
                "job.failed",
                "model.candidate_ready",
                "model.promoted",
                "predictions.updated",
                "inspection_plan.ready",
                "verification.contradicts_model",
                "wq.alert.opened",
                "wq.alert.resolved",
                "wq.compliance.exceedance",
                "sewer.overflow_risk.raised",
                "sewer.dry_weather_overflow.detected",
                "export.ready"
              ]
            },
            "description": "Event types this subscription receives."
          },
          "enabled": {
            "type": "boolean"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Short label."
          },
          "secret": {
            "type": "string",
            "minLength": 8,
            "maxLength": 200,
            "description": "New signing secret when the request set rotate to true. Shown once. Absent otherwise. Not a live credential."
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "enabled"
        ]
      },
      "WebhookReplay": {
        "type": "object",
        "additionalProperties": false,
        "description": "Which dead-lettered delivery to send again.",
        "properties": {
          "delivery_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "webhook-id of the delivery to replay."
          }
        },
        "required": [
          "delivery_id"
        ]
      },
      "ApiKeyCreate": {
        "type": "object",
        "additionalProperties": false,
        "description": "A new API key. The secret is not stored in this request.",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
          },
          "scopes": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "lsl:read",
                "lsl:write",
                "lsl:promote",
                "wq:read",
                "wq:write",
                "sewer:read",
                "sewer:write",
                "jobs:read",
                "jobs:write",
                "platform:read",
                "platform:write",
                "audit:read",
                "admin"
              ]
            },
            "description": "Scopes granted to the key. admin satisfies every operation."
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "UTC expiry. Null means no expiry."
          }
        },
        "required": [
          "name",
          "scopes"
        ]
      },
      "ApiKey": {
        "type": "object",
        "additionalProperties": false,
        "description": "A stored API key. secret is null after the create response.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the key."
          },
          "name": {
            "type": "string",
            "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
          },
          "prefix": {
            "type": "string",
            "pattern": "^cp_[a-z0-9]{8}$",
            "description": "Public prefix used for lookup."
          },
          "scopes": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "lsl:read",
                "lsl:write",
                "lsl:promote",
                "wq:read",
                "wq:write",
                "sewer:read",
                "sewer:write",
                "jobs:read",
                "jobs:write",
                "platform:read",
                "platform:write",
                "audit:read",
                "admin"
              ]
            },
            "description": "Scopes granted to the key. admin satisfies every operation."
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "UTC expiry."
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "UTC time of the last accepted use."
          },
          "secret": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 8,
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "description": "Shown once on create or rotation. Otherwise null."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "prefix",
          "scopes",
          "secret",
          "created_at"
        ]
      },
      "ApiKeyCreated": {
        "type": "object",
        "additionalProperties": false,
        "description": "Create response. secret is shown once.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the key."
          },
          "name": {
            "type": "string",
            "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
          },
          "prefix": {
            "type": "string",
            "pattern": "^cp_[a-z0-9]{8}$"
          },
          "scopes": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "lsl:read",
                "lsl:write",
                "lsl:promote",
                "wq:read",
                "wq:write",
                "sewer:read",
                "sewer:write",
                "jobs:read",
                "jobs:write",
                "platform:read",
                "platform:write",
                "audit:read",
                "admin"
              ]
            },
            "description": "Scopes granted to the key. admin satisfies every operation."
          },
          "secret": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 8,
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "description": "Present on the first response only."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "prefix",
          "scopes",
          "secret",
          "created_at"
        ]
      },
      "ApiKeyUpdate": {
        "type": "object",
        "additionalProperties": false,
        "description": "Replacement key settings. rotate returns a new secret on ApiKey.secret.",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
          },
          "scopes": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "lsl:read",
                "lsl:write",
                "lsl:promote",
                "wq:read",
                "wq:write",
                "sewer:read",
                "sewer:write",
                "jobs:read",
                "jobs:write",
                "platform:read",
                "platform:write",
                "audit:read",
                "admin"
              ]
            },
            "description": "Scopes granted to the key. admin satisfies every operation."
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "UTC expiry."
          },
          "rotate": {
            "type": "boolean"
          }
        },
        "required": [
          "name",
          "scopes"
        ]
      },
      "AuditEvent": {
        "type": "object",
        "additionalProperties": false,
        "description": "One hash-chained audit event. The chain has no personal names.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the audit event."
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time"
          },
          "action": {
            "type": "string",
            "pattern": "^[a-z0-9._:-]{1,64}$"
          },
          "actor_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the actor. Not a name."
          },
          "hash": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$",
            "description": "SHA-256 of this row."
          },
          "previous_hash": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$",
            "description": "SHA-256 of the previous row. The first row uses 64 zeroes."
          }
        },
        "required": [
          "id",
          "occurred_at",
          "action",
          "actor_id",
          "hash",
          "previous_hash"
        ]
      },
      "ConnectorCreate": {
        "type": "object",
        "additionalProperties": false,
        "description": "A connector. config holds non-secret settings only.",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
          },
          "kind": {
            "type": "string",
            "enum": [
              "files",
              "arcgis",
              "lims_csv",
              "scada_csv",
              "echo",
              "usgs",
              "noaa"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "config": {
            "type": "object",
            "description": "Non-secret settings, such as a base URL.",
            "additionalProperties": {
              "type": "string",
              "maxLength": 200
            }
          }
        },
        "required": [
          "name",
          "kind"
        ]
      },
      "Connector": {
        "type": "object",
        "additionalProperties": false,
        "description": "A stored connector.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the connector."
          },
          "name": {
            "type": "string",
            "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
          },
          "kind": {
            "type": "string",
            "enum": [
              "files",
              "arcgis",
              "lims_csv",
              "scada_csv",
              "echo",
              "usgs",
              "noaa"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "config": {
            "type": "object",
            "description": "Non-secret settings.",
            "additionalProperties": {
              "type": "string",
              "maxLength": 200
            }
          }
        },
        "required": [
          "id",
          "name",
          "kind",
          "enabled"
        ]
      },
      "ConnectorUpdate": {
        "type": "object",
        "additionalProperties": false,
        "description": "Replacement connector settings.",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
          },
          "enabled": {
            "type": "boolean"
          },
          "config": {
            "type": "object",
            "description": "Non-secret settings.",
            "additionalProperties": {
              "type": "string",
              "maxLength": 200
            }
          }
        },
        "required": [
          "name",
          "enabled"
        ]
      },
      "Module": {
        "type": "object",
        "additionalProperties": false,
        "description": "An installed module.",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]{0,63}$"
          },
          "version": {
            "type": "string",
            "pattern": "^[A-Za-z0-9._-]{1,32}$"
          },
          "enabled": {
            "type": "boolean"
          }
        },
        "required": [
          "name",
          "version",
          "enabled"
        ]
      },
      "Health": {
        "type": "object",
        "additionalProperties": false,
        "description": "Process health.",
        "properties": {
          "status": {
            "const": "ok"
          }
        },
        "required": [
          "status"
        ]
      },
      "Version": {
        "type": "object",
        "additionalProperties": false,
        "description": "Contract version.",
        "properties": {
          "api": {
            "const": "v1"
          },
          "version": {
            "const": "1.0.0"
          }
        },
        "required": [
          "api",
          "version"
        ]
      },
      "TrainModelRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Training request. The model version is produced by the job.",
        "properties": {
          "algorithm": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_.:-]{1,64}$"
          },
          "training_snapshot_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the training snapshot."
          },
          "params": {
            "type": "object",
            "additionalProperties": true,
            "description": "Algorithm parameters as JSON."
          }
        },
        "required": [
          "algorithm",
          "training_snapshot_id"
        ]
      },
      "PromoteModelRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Optional note recorded with the promotion.",
        "properties": {
          "note": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[A-Za-z0-9 ._-]{1,120}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Short note. No personal data."
          }
        }
      },
      "ScoreRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Batch score request.",
        "properties": {
          "model_version_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the model."
          },
          "data_snapshot_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the snapshot to score."
          }
        },
        "required": [
          "model_version_id",
          "data_snapshot_id"
        ]
      },
      "PredictRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Synchronous prediction for at most 1000 service lines.",
        "properties": {
          "model_version_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the model."
          },
          "service_line_ids": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1000,
            "items": {
              "type": "string",
              "format": "uuid",
              "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
              "description": "UUIDv7 of a service line."
            }
          }
        },
        "required": [
          "model_version_id",
          "service_line_ids"
        ]
      },
      "PredictResponse": {
        "type": "object",
        "additionalProperties": false,
        "description": "Predictions for the requested lines.",
        "properties": {
          "model_version_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the model."
          },
          "predictions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Prediction"
            }
          }
        },
        "required": [
          "model_version_id",
          "predictions"
        ]
      },
      "ExportRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Export request. lcri_baseline is the inventory baseline file.",
        "properties": {
          "format": {
            "type": "string",
            "enum": [
              "lcri_baseline",
              "geojson",
              "gpkg",
              "csv",
              "arcgis"
            ]
          },
          "model_version_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the model, when the export uses scores."
          }
        },
        "required": [
          "format"
        ]
      },
      "ReportRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Model report request.",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "model",
              "inventory"
            ]
          },
          "model_version_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the model."
          }
        },
        "required": [
          "kind"
        ]
      },
      "Report": {
        "type": "object",
        "additionalProperties": false,
        "description": "A report produced by a job.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the report."
          },
          "kind": {
            "type": "string",
            "enum": [
              "model",
              "inventory"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "succeeded",
              "failed"
            ]
          },
          "job_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
            "description": "UUIDv7 of the report job."
          },
          "href": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "description": "Download URL when succeeded."
          }
        },
        "required": [
          "id",
          "kind",
          "status",
          "job_id"
        ]
      },
      "InspectionPlanRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Inputs for an inspection plan.",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "REPRESENTATIVE",
              "REPLACEMENT",
              "MIXED",
              "LCRI_VALIDATION"
            ]
          },
          "budget_n": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000000
          },
          "probability_share": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "seed": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "mode",
          "budget_n",
          "seed"
        ]
      },
      "ValidationPlanRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Inputs for a validation plan.",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "REPRESENTATIVE",
              "REPLACEMENT",
              "MIXED",
              "LCRI_VALIDATION"
            ]
          },
          "budget_n": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000000
          },
          "seed": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "mode",
          "budget_n",
          "seed"
        ]
      },
      "ValidationResultsRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Field results for one validation plan.",
        "properties": {
          "verifications": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/Verification"
            }
          }
        },
        "required": [
          "verifications"
        ]
      },
      "ValidationResults": {
        "type": "object",
        "additionalProperties": false,
        "description": "How many verification rows were accepted.",
        "properties": {
          "accepted": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "accepted"
        ]
      },
      "ValidationDesignRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Inventory CSV and the draw settings. The server stores nothing.",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "LCRI_VALIDATION",
              "REPRESENTATIVE"
            ]
          },
          "budget_n": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100000
          },
          "probability_share": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "seed": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9223372036854775807
          },
          "inventory_version": {
            "type": "string",
            "pattern": "^[A-Za-z0-9._:-]{1,80}$"
          },
          "state_ban_year": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1800,
                "maximum": 2100
              },
              {
                "type": "null"
              }
            ]
          },
          "inventory_csv": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000000
          }
        },
        "required": [
          "mode",
          "budget_n",
          "probability_share",
          "seed",
          "inventory_version",
          "inventory_csv"
        ]
      },
      "ValidationDesign": {
        "type": "object",
        "additionalProperties": false,
        "description": "The sample, the design facts, and the regulator pack HTML.",
        "properties": {
          "design": {
            "type": "object",
            "additionalProperties": false,
            "description": "Facts for the sample. Line ids stay in sample_csv.",
            "required": [
              "budget_curve",
              "budget_n",
              "effective_ban",
              "exclusions",
              "federal_ban",
              "git_sha",
              "inclusion_summary",
              "inspection_methods",
              "inventory_version",
              "missing_columns",
              "mode",
              "package_version",
              "pool_definition",
              "pool_size",
              "probability_share",
              "reproduce_command",
              "row_count",
              "sample_size",
              "schedule_end_year",
              "schedule_start_year",
              "seed",
              "state_ban",
              "strata",
              "table_row"
            ],
            "properties": {
              "budget_curve": {
                "anyOf": [
                  {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "budget",
                        "picks",
                        "strata_used",
                        "pi_min",
                        "pi_median",
                        "pi_max",
                        "note"
                      ],
                      "properties": {
                        "budget": {
                          "type": "integer"
                        },
                        "picks": {
                          "anyOf": [
                            {
                              "type": "integer"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "strata_used": {
                          "anyOf": [
                            {
                              "type": "integer"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "pi_min": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "pi_median": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "pi_max": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "note": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "budget_n": {
                "type": "integer"
              },
              "effective_ban": {
                "type": "string"
              },
              "exclusions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "count",
                    "reason"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "reason": {
                      "type": "string"
                    }
                  }
                }
              },
              "federal_ban": {
                "type": "string"
              },
              "git_sha": {
                "type": "string"
              },
              "inclusion_summary": {
                "type": "string"
              },
              "inspection_methods": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "VISUAL_1PT",
                    "VISUAL_2PT",
                    "POTHOLE",
                    "EXCAVATION",
                    "CCTV",
                    "CUSTOMER_PHOTO",
                    "RECORD",
                    "XRF",
                    "MAGNET_SCRATCH"
                  ]
                }
              },
              "inventory_version": {
                "type": "string"
              },
              "missing_columns": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "mode": {
                "type": "string"
              },
              "package_version": {
                "type": "string"
              },
              "pool_definition": {
                "type": "string"
              },
              "pool_size": {
                "type": "integer",
                "minimum": 0
              },
              "probability_share": {
                "type": "string"
              },
              "reproduce_command": {
                "type": "string"
              },
              "row_count": {
                "type": "integer",
                "minimum": 0
              },
              "sample_size": {
                "type": "integer",
                "minimum": 0
              },
              "schedule_end_year": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "schedule_start_year": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "seed": {
                "type": "integer",
                "minimum": 0
              },
              "state_ban": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "strata": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "allocation",
                    "inclusion_sum",
                    "population",
                    "stratum"
                  ],
                  "properties": {
                    "allocation": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "inclusion_sum": {
                      "type": "string"
                    },
                    "population": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "stratum": {
                      "type": "string"
                    }
                  }
                }
              },
              "table_row": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          "sample_csv": {
            "type": "string",
            "minLength": 1
          },
          "pack_html": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "design",
          "sample_csv",
          "pack_html"
        ]
      },
      "DatasetPage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Dataset"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "WebhookPage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "ApiKeyPage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiKey"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "AuditEventPage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuditEvent"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "ConnectorPage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Connector"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "ModulePage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Module"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "ModelVersionPage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModelVersion"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "PredictionPage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Prediction"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "VerificationPage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Verification"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "EstimatePage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Estimate"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "InspectionPlanPage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InspectionPlan"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "ReportPage": {
        "type": "object",
        "additionalProperties": false,
        "description": "One page. next_cursor is null on the last page.",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Report"
            }
          },
          "next_cursor": {
            "description": "Opaque cursor for the next page. Null on the last page.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "ModelVersion": {
        "$defs": {
          "JsonValue": {},
          "ModelStatus": {
            "enum": [
              "CANDIDATE",
              "PROMOTED",
              "RETIRED"
            ],
            "title": "ModelStatus",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "description": "Lineage for one trained model. The id field name follows section 4.1.",
        "examples": [
          {
            "algorithm": "rules",
            "code_commit": "0000000000000000000000000000000000000006",
            "eval_report_id": "018bcfe5-6800-7000-8000-000000000008",
            "feature_set_hash": "0000000000000000000000000000000000000000000000000000000000000006",
            "id": "018bcfe5-6800-7000-8000-000000000006",
            "params": {
              "seed": 6
            },
            "promoted_at": null,
            "promoted_by": null,
            "schema_version": "2.1.0",
            "status": "CANDIDATE",
            "training_snapshot_id": "018bcfe5-6800-7000-8000-000000000007"
          }
        ],
        "properties": {
          "algorithm": {
            "description": "Algorithm name.",
            "pattern": "^[A-Za-z0-9_.:-]{1,64}$",
            "title": "Algorithm",
            "type": "string"
          },
          "code_commit": {
            "description": "Full git commit SHA.",
            "pattern": "^[0-9a-f]{40}$",
            "title": "Code Commit",
            "type": "string"
          },
          "eval_report_id": {
            "description": "UUIDv7 of the evaluation report.",
            "format": "uuid",
            "title": "Eval Report Id",
            "type": "string"
          },
          "feature_set_hash": {
            "description": "SHA-256 of the feature set.",
            "pattern": "^[0-9a-f]{64}$",
            "title": "Feature Set Hash",
            "type": "string"
          },
          "id": {
            "description": "UUIDv7 primary id.",
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "params": {
            "additionalProperties": {
              "$ref": "#/components/schemas/ModelVersion/$defs/JsonValue"
            },
            "description": "JSON parameters.",
            "title": "Params",
            "type": "object"
          },
          "promoted_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "UTC promotion time. Required when status is PROMOTED.",
            "title": "Promoted At"
          },
          "promoted_by": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "UUIDv7 of the approver. Required when status is PROMOTED.",
            "title": "Promoted By"
          },
          "schema_version": {
            "default": "2.1.0",
            "description": "C1 schema version. This release writes 2.1.0. Readers accept 2.0.0 and 2.1.0. 2.1.0 is additive to 2.0.0.",
            "enum": [
              "2.0.0",
              "2.1.0"
            ],
            "title": "Schema Version",
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/ModelVersion/$defs/ModelStatus",
            "description": "CANDIDATE, PROMOTED, or RETIRED."
          },
          "training_snapshot_id": {
            "description": "UUIDv7 of the training snapshot.",
            "format": "uuid",
            "title": "Training Snapshot Id",
            "type": "string"
          }
        },
        "required": [
          "id",
          "algorithm",
          "params",
          "feature_set_hash",
          "training_snapshot_id",
          "code_commit",
          "eval_report_id",
          "status"
        ],
        "title": "ModelVersion",
        "type": "object"
      },
      "Prediction": {
        "$defs": {
          "PredictedClass": {
            "enum": [
              "LEAD",
              "GRR",
              "NON_LEAD"
            ],
            "title": "PredictedClass",
            "type": "string"
          },
          "TopFactor": {
            "additionalProperties": false,
            "description": "One feature contribution on a prediction.",
            "properties": {
              "contribution": {
                "description": "Signed contribution.",
                "title": "Contribution",
                "type": "number"
              },
              "feature": {
                "description": "Feature name.",
                "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$",
                "title": "Feature",
                "type": "string"
              }
            },
            "required": [
              "feature",
              "contribution"
            ],
            "title": "TopFactor",
            "type": "object"
          }
        },
        "additionalProperties": false,
        "description": "Class probabilities for one service line. They sum to 1 within 1e-6.",
        "examples": [
          {
            "abstain": false,
            "alpha": 0.05,
            "conformal_set": [
              "NON_LEAD"
            ],
            "data_snapshot_id": "018bcfe5-6800-7000-8000-000000000008",
            "model_version_id": "018bcfe5-6800-7000-8000-000000000007",
            "p_grr": 0.1,
            "p_lead": 0.2,
            "p_non_lead": 0.7,
            "prediction_id": "018bcfe5-6800-7000-8000-000000000005",
            "schema_version": "2.1.0",
            "service_line_id": "018bcfe5-6800-7000-8000-000000000006",
            "top_factors": [
              {
                "contribution": -0.1,
                "feature": "year_built"
              }
            ]
          }
        ],
        "properties": {
          "abstain": {
            "description": "True exactly when the conformal set holds more than one class.",
            "title": "Abstain",
            "type": "boolean"
          },
          "alpha": {
            "description": "Conformal miscoverage level in (0, 1).",
            "exclusiveMaximum": 1,
            "exclusiveMinimum": 0,
            "title": "Alpha",
            "type": "number"
          },
          "conformal_set": {
            "description": "Classes in the conformal set. One class is a call.",
            "items": {
              "$ref": "#/components/schemas/Prediction/$defs/PredictedClass"
            },
            "maxItems": 3,
            "minItems": 1,
            "title": "Conformal Set",
            "type": "array"
          },
          "data_snapshot_id": {
            "description": "UUIDv7 of the data snapshot.",
            "format": "uuid",
            "title": "Data Snapshot Id",
            "type": "string"
          },
          "model_version_id": {
            "description": "UUIDv7 of the model version.",
            "format": "uuid",
            "title": "Model Version Id",
            "type": "string"
          },
          "p_grr": {
            "description": "Probability of GRR.",
            "maximum": 1,
            "minimum": 0,
            "title": "P Grr",
            "type": "number"
          },
          "p_lead": {
            "description": "Probability of LEAD.",
            "maximum": 1,
            "minimum": 0,
            "title": "P Lead",
            "type": "number"
          },
          "p_non_lead": {
            "description": "Probability of NON_LEAD.",
            "maximum": 1,
            "minimum": 0,
            "title": "P Non Lead",
            "type": "number"
          },
          "prediction_id": {
            "description": "UUIDv7 primary id.",
            "format": "uuid",
            "title": "Prediction Id",
            "type": "string"
          },
          "schema_version": {
            "default": "2.1.0",
            "description": "C1 schema version. This release writes 2.1.0. Readers accept 2.0.0 and 2.1.0. 2.1.0 is additive to 2.0.0.",
            "enum": [
              "2.0.0",
              "2.1.0"
            ],
            "title": "Schema Version",
            "type": "string"
          },
          "service_line_id": {
            "description": "UUIDv7 of the service line.",
            "format": "uuid",
            "title": "Service Line Id",
            "type": "string"
          },
          "top_factors": {
            "description": "Largest feature contributions.",
            "items": {
              "$ref": "#/components/schemas/Prediction/$defs/TopFactor"
            },
            "maxItems": 20,
            "title": "Top Factors",
            "type": "array"
          }
        },
        "required": [
          "prediction_id",
          "service_line_id",
          "model_version_id",
          "p_lead",
          "p_grr",
          "p_non_lead",
          "conformal_set",
          "alpha",
          "abstain",
          "data_snapshot_id"
        ],
        "title": "Prediction",
        "type": "object"
      },
      "Verification": {
        "$defs": {
          "EvidenceKind": {
            "enum": [
              "PHOTO",
              "INSPECTOR_SIGN_OFF"
            ],
            "title": "EvidenceKind",
            "type": "string"
          },
          "EvidenceRef": {
            "additionalProperties": false,
            "description": "The photo or inspector sign-off that makes an instrument reading count.",
            "properties": {
              "kind": {
                "$ref": "#/components/schemas/Verification/$defs/EvidenceKind",
                "description": "PHOTO or INSPECTOR_SIGN_OFF."
              },
              "ref": {
                "description": "Relative photo object key, or the sign-off record id. Never a name.",
                "pattern": "^[A-Za-z0-9_./-]{1,200}$",
                "title": "Ref",
                "type": "string"
              }
            },
            "required": [
              "kind",
              "ref"
            ],
            "title": "EvidenceRef",
            "type": "object"
          },
          "Reading": {
            "additionalProperties": false,
            "description": "One instrument reading with its unit.",
            "properties": {
              "unit": {
                "description": "Unit token, for example mg/cm2 or ppm.",
                "pattern": "^[A-Za-z0-9%./_-]{1,32}$",
                "title": "Unit",
                "type": "string"
              },
              "value": {
                "description": "Reading value.",
                "title": "Value",
                "type": "number"
              }
            },
            "required": [
              "value",
              "unit"
            ],
            "title": "Reading",
            "type": "object"
          },
          "Selection": {
            "additionalProperties": false,
            "description": "How a verification entered the sample. Inclusion probability keeps estimates unbiased.",
            "properties": {
              "batch_id": {
                "anyOf": [
                  {
                    "format": "uuid",
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "UUIDv7 of the sample batch.",
                "title": "Batch Id"
              },
              "design": {
                "$ref": "#/components/schemas/Verification/$defs/SelectionDesign",
                "description": "Sampling design."
              },
              "inclusion_probability": {
                "anyOf": [
                  {
                    "exclusiveMinimum": 0,
                    "maximum": 1,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Known inclusion probability in (0, 1]. Required for probability designs.",
                "title": "Inclusion Probability"
              }
            },
            "required": [
              "design"
            ],
            "title": "Selection",
            "type": "object"
          },
          "SelectionDesign": {
            "enum": [
              "RANDOM_VALIDATION",
              "PROBABILITY_SAMPLE",
              "ACTIVE_LEARNING",
              "REPLACEMENT_PRIORITY",
              "OPPORTUNISTIC",
              "CUSTOMER_REQUEST",
              "UNKNOWN"
            ],
            "title": "SelectionDesign",
            "type": "string"
          },
          "SideName": {
            "enum": [
              "UTILITY",
              "CUSTOMER",
              "CONNECTOR"
            ],
            "title": "SideName",
            "type": "string"
          },
          "VerificationDetail": {
            "additionalProperties": false,
            "description": "Instrument, reading, and evidence for a field reading. Added in C1 2.1.0.\n\nXRF and MAGNET_SCRATCH need evidence_ref: a reading counts as a\nverification only with the photo or inspector sign-off the state's\nrule asks for (DIRECTION decision 22).",
            "properties": {
              "evidence_ref": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Verification/$defs/EvidenceRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Photo or inspector sign-off. Required for XRF and MAGNET_SCRATCH."
              },
              "instrument_make": {
                "anyOf": [
                  {
                    "pattern": "^[A-Za-z0-9 ._-]{1,120}$",
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Instrument make.",
                "title": "Instrument Make"
              },
              "instrument_model": {
                "anyOf": [
                  {
                    "pattern": "^[A-Za-z0-9 ._-]{1,120}$",
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Instrument model.",
                "title": "Instrument Model"
              },
              "instrument_serial": {
                "anyOf": [
                  {
                    "pattern": "^[A-Za-z0-9_.:/-]{1,64}$",
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Instrument serial number.",
                "title": "Instrument Serial"
              },
              "reading": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Verification/$defs/Reading"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "The reading with its unit."
              }
            },
            "title": "VerificationDetail",
            "type": "object"
          },
          "VerificationMethod": {
            "enum": [
              "VISUAL_1PT",
              "VISUAL_2PT",
              "POTHOLE",
              "EXCAVATION",
              "CCTV",
              "CUSTOMER_PHOTO",
              "RECORD",
              "XRF",
              "MAGNET_SCRATCH"
            ],
            "title": "VerificationMethod",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "description": "A field or record check of one side or of the connector.",
        "examples": [
          {
            "method": "POTHOLE",
            "notes_text": "synthetic field note",
            "observed_at": "2024-06-15T12:00:00Z",
            "observed_material": "COPPER",
            "photo_refs": [
              "synthetic/photos/3.bin"
            ],
            "schema_version": "2.1.0",
            "selection": {
              "batch_id": null,
              "design": "CUSTOMER_REQUEST",
              "inclusion_probability": null
            },
            "service_line_id": "018bcfe5-6800-7000-8000-000000000004",
            "side": "UTILITY",
            "verification_detail": null,
            "verification_id": "018bcfe5-6800-7000-8000-000000000003"
          }
        ],
        "properties": {
          "method": {
            "$ref": "#/components/schemas/Verification/$defs/VerificationMethod",
            "description": "How the material was observed."
          },
          "notes_text": {
            "default": "",
            "description": "Notes. Scrubbing of names happens on ingest.",
            "maxLength": 4000,
            "title": "Notes Text",
            "type": "string"
          },
          "observed_at": {
            "description": "UTC timestamp of the observation.",
            "format": "date-time",
            "title": "Observed At",
            "type": "string"
          },
          "observed_material": {
            "description": "Material code legal for the side.",
            "title": "Observed Material",
            "type": "string"
          },
          "photo_refs": {
            "description": "Relative object keys for photos.",
            "items": {
              "type": "string"
            },
            "maxItems": 20,
            "title": "Photo Refs",
            "type": "array"
          },
          "schema_version": {
            "default": "2.1.0",
            "description": "C1 schema version. This release writes 2.1.0. Readers accept 2.0.0 and 2.1.0. 2.1.0 is additive to 2.0.0.",
            "enum": [
              "2.0.0",
              "2.1.0"
            ],
            "title": "Schema Version",
            "type": "string"
          },
          "selection": {
            "$ref": "#/components/schemas/Verification/$defs/Selection",
            "description": "Why this line was selected."
          },
          "service_line_id": {
            "description": "UUIDv7 of the service line.",
            "format": "uuid",
            "title": "Service Line Id",
            "type": "string"
          },
          "side": {
            "$ref": "#/components/schemas/Verification/$defs/SideName",
            "description": "UTILITY, CUSTOMER, or CONNECTOR."
          },
          "verification_detail": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Verification/$defs/VerificationDetail"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Instrument, reading, and evidence. Required for XRF and MAGNET_SCRATCH."
          },
          "verification_id": {
            "description": "UUIDv7 primary id.",
            "format": "uuid",
            "title": "Verification Id",
            "type": "string"
          }
        },
        "required": [
          "verification_id",
          "service_line_id",
          "side",
          "method",
          "observed_material",
          "observed_at",
          "selection"
        ],
        "title": "Verification",
        "type": "object"
      },
      "EvalReport": {
        "$defs": {
          "GateDecision": {
            "additionalProperties": false,
            "description": "PASS with no reasons; FAIL or INSUFFICIENT with at least one reason",
            "properties": {
              "decision": {
                "$ref": "#/components/schemas/EvalReport/$defs/GateResult",
                "description": "PASS, FAIL, or INSUFFICIENT."
              },
              "reasons": {
                "description": "Empty on PASS. At least one short reason on FAIL or INSUFFICIENT.",
                "items": {
                  "type": "string"
                },
                "maxItems": 20,
                "title": "Reasons",
                "type": "array"
              }
            },
            "required": [
              "decision"
            ],
            "title": "GateDecision",
            "type": "object"
          },
          "GateResult": {
            "enum": [
              "PASS",
              "FAIL",
              "INSUFFICIENT"
            ],
            "title": "GateResult",
            "type": "string"
          },
          "IntervalEstimate": {
            "additionalProperties": false,
            "description": "A numeric interval with its level.",
            "properties": {
              "level": {
                "description": "Interval level in (0, 1).",
                "exclusiveMaximum": 1,
                "exclusiveMinimum": 0,
                "title": "Level",
                "type": "number"
              },
              "lower": {
                "description": "Lower bound.",
                "title": "Lower",
                "type": "number"
              },
              "upper": {
                "description": "Upper bound.",
                "title": "Upper",
                "type": "number"
              }
            },
            "required": [
              "lower",
              "upper",
              "level"
            ],
            "title": "IntervalEstimate",
            "type": "object"
          },
          "JsonValue": {},
          "MetricGroup": {
            "additionalProperties": false,
            "description": "Metrics for the whole set, one fold, or one group.",
            "properties": {
              "group_key": {
                "anyOf": [
                  {
                    "pattern": "^[A-Za-z0-9_-]{1,64}$",
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Null for OVERALL. A token for FOLD and GROUP.",
                "title": "Group Key"
              },
              "metrics": {
                "description": "Metrics in this group.",
                "items": {
                  "$ref": "#/components/schemas/EvalReport/$defs/MetricValue"
                },
                "minItems": 1,
                "title": "Metrics",
                "type": "array"
              },
              "scope": {
                "$ref": "#/components/schemas/EvalReport/$defs/MetricScope",
                "description": "OVERALL, FOLD, or GROUP."
              }
            },
            "required": [
              "scope",
              "metrics"
            ],
            "title": "MetricGroup",
            "type": "object"
          },
          "MetricScope": {
            "enum": [
              "OVERALL",
              "FOLD",
              "GROUP"
            ],
            "title": "MetricScope",
            "type": "string"
          },
          "MetricValue": {
            "additionalProperties": false,
            "description": "One named metric, with an optional interval.",
            "properties": {
              "estimate": {
                "description": "Point estimate.",
                "title": "Estimate",
                "type": "number"
              },
              "interval": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/EvalReport/$defs/IntervalEstimate"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "description": "Optional interval."
              },
              "name": {
                "description": "Metric name.",
                "pattern": "^[A-Za-z0-9_-]{1,64}$",
                "title": "Name",
                "type": "string"
              }
            },
            "required": [
              "name",
              "estimate"
            ],
            "title": "MetricValue",
            "type": "object"
          }
        },
        "additionalProperties": false,
        "description": "Evaluation report consumed by reports, the API, and the UI.\n\nNested metric details beyond the fields here belong to craftpine.eval.\nThe objects are JSON so a later contract change can tighten them.",
        "examples": [
          {
            "bias_diagnostics": {
              "auc": 0.5
            },
            "calibration": {
              "ece": 0.02
            },
            "conformal": {
              "alpha": 0.05
            },
            "dataset_card": {
              "label": "synthetic"
            },
            "drift": {
              "psi": 0.0
            },
            "equity": {
              "status": "synthetic"
            },
            "gate_decision": {
              "decision": "PASS",
              "reasons": []
            },
            "leakage": {
              "canary": true
            },
            "metrics": [
              {
                "group_key": null,
                "metrics": [
                  {
                    "estimate": 0.4,
                    "interval": {
                      "level": 0.95,
                      "lower": 0.2,
                      "upper": 0.6
                    },
                    "name": "log_loss"
                  }
                ],
                "scope": "OVERALL"
              }
            ],
            "model_card": {
              "algorithm": "rules"
            },
            "red_team": {
              "passed": true
            },
            "report_id": "018bcfe5-6800-7000-8000-000000000009",
            "schema_version": "2.1.0",
            "seeds": [
              9
            ],
            "split_strategy": "spatial_block",
            "versions": {
              "eval": "0.0.0"
            }
          }
        ],
        "properties": {
          "bias_diagnostics": {
            "additionalProperties": {
              "$ref": "#/components/schemas/EvalReport/$defs/JsonValue"
            },
            "description": "Sampling-bias section.",
            "title": "Bias Diagnostics",
            "type": "object"
          },
          "calibration": {
            "additionalProperties": {
              "$ref": "#/components/schemas/EvalReport/$defs/JsonValue"
            },
            "description": "Calibration section.",
            "title": "Calibration",
            "type": "object"
          },
          "conformal": {
            "additionalProperties": {
              "$ref": "#/components/schemas/EvalReport/$defs/JsonValue"
            },
            "description": "Conformal section.",
            "title": "Conformal",
            "type": "object"
          },
          "dataset_card": {
            "additionalProperties": {
              "$ref": "#/components/schemas/EvalReport/$defs/JsonValue"
            },
            "description": "Dataset card JSON.",
            "title": "Dataset Card",
            "type": "object"
          },
          "drift": {
            "additionalProperties": {
              "$ref": "#/components/schemas/EvalReport/$defs/JsonValue"
            },
            "description": "Drift section.",
            "title": "Drift",
            "type": "object"
          },
          "equity": {
            "additionalProperties": {
              "$ref": "#/components/schemas/EvalReport/$defs/JsonValue"
            },
            "description": "Equity section.",
            "title": "Equity",
            "type": "object"
          },
          "gate_decision": {
            "$ref": "#/components/schemas/EvalReport/$defs/GateDecision",
            "description": "Release gate."
          },
          "leakage": {
            "additionalProperties": {
              "$ref": "#/components/schemas/EvalReport/$defs/JsonValue"
            },
            "description": "Leakage section.",
            "title": "Leakage",
            "type": "object"
          },
          "metrics": {
            "description": "Overall, fold, and group metrics.",
            "items": {
              "$ref": "#/components/schemas/EvalReport/$defs/MetricGroup"
            },
            "minItems": 1,
            "title": "Metrics",
            "type": "array"
          },
          "model_card": {
            "additionalProperties": {
              "$ref": "#/components/schemas/EvalReport/$defs/JsonValue"
            },
            "description": "Model card JSON.",
            "title": "Model Card",
            "type": "object"
          },
          "red_team": {
            "additionalProperties": {
              "$ref": "#/components/schemas/EvalReport/$defs/JsonValue"
            },
            "description": "Red-team section.",
            "title": "Red Team",
            "type": "object"
          },
          "report_id": {
            "description": "UUIDv7 primary id.",
            "format": "uuid",
            "title": "Report Id",
            "type": "string"
          },
          "schema_version": {
            "default": "2.1.0",
            "description": "C1 schema version. This release writes 2.1.0. Readers accept 2.0.0 and 2.1.0. 2.1.0 is additive to 2.0.0.",
            "enum": [
              "2.0.0",
              "2.1.0"
            ],
            "title": "Schema Version",
            "type": "string"
          },
          "seeds": {
            "description": "Seeds used in the run.",
            "items": {
              "type": "integer"
            },
            "maxItems": 32,
            "minItems": 1,
            "title": "Seeds",
            "type": "array"
          },
          "split_strategy": {
            "description": "Split strategy code.",
            "pattern": "^[a-z0-9_:-]{1,64}$",
            "title": "Split Strategy",
            "type": "string"
          },
          "versions": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Named versions.",
            "minProperties": 1,
            "title": "Versions",
            "type": "object"
          }
        },
        "required": [
          "report_id",
          "dataset_card",
          "model_card",
          "split_strategy",
          "metrics",
          "calibration",
          "conformal",
          "bias_diagnostics",
          "equity",
          "red_team",
          "leakage",
          "drift",
          "gate_decision",
          "versions",
          "seeds"
        ],
        "title": "EvalReport",
        "type": "object"
      },
      "JobSucceededEvent": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "title": "job.succeeded",
        "description": "The worker finished a job. Delivered at least once.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "id",
          "time",
          "data"
        ],
        "properties": {
          "type": {
            "const": "job.succeeded"
          },
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Same value as the webhook-id header."
          },
          "time": {
            "type": "string",
            "format": "date-time",
            "description": "UTC time the event was emitted."
          },
          "data": {
            "type": "object",
            "additionalProperties": false,
            "description": "A finished job.",
            "required": [
              "job_id",
              "kind",
              "status",
              "result_links"
            ],
            "properties": {
              "job_id": {
                "type": "string",
                "format": "uuid",
                "description": "UUIDv7 of the job."
              },
              "kind": {
                "type": "string",
                "pattern": "^[a-z0-9._:-]{1,64}$"
              },
              "status": {
                "const": "succeeded"
              },
              "result_links": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "rel",
                    "href"
                  ],
                  "properties": {
                    "rel": {
                      "type": "string",
                      "pattern": "^[a-z0-9._:-]{1,32}$"
                    },
                    "href": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                },
                "description": "Links to the job and its result."
              }
            }
          }
        },
        "examples": [
          {
            "type": "job.succeeded",
            "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
            "time": "2026-10-23T16:00:00Z",
            "data": {
              "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
              "kind": "lsl.model.train",
              "status": "succeeded",
              "result_links": [
                {
                  "rel": "self",
                  "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              ]
            }
          }
        ]
      },
      "JobFailedEvent": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "title": "job.failed",
        "description": "The worker failed a job.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "id",
          "time",
          "data"
        ],
        "properties": {
          "type": {
            "const": "job.failed"
          },
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Same value as the webhook-id header."
          },
          "time": {
            "type": "string",
            "format": "date-time",
            "description": "UTC time the event was emitted."
          },
          "data": {
            "type": "object",
            "additionalProperties": false,
            "description": "A job that failed.",
            "required": [
              "job_id",
              "kind",
              "status",
              "error"
            ],
            "properties": {
              "job_id": {
                "type": "string",
                "format": "uuid",
                "description": "UUIDv7 of the job."
              },
              "kind": {
                "type": "string",
                "pattern": "^[a-z0-9._:-]{1,64}$"
              },
              "status": {
                "const": "failed"
              },
              "error": {
                "type": "object",
                "additionalProperties": true,
                "description": "RFC 9457 problem details for a failed job.",
                "required": [
                  "type",
                  "title",
                  "status"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "format": "uri"
                  },
                  "title": {
                    "type": "string"
                  },
                  "status": {
                    "type": "integer"
                  },
                  "detail": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "examples": [
          {
            "type": "job.failed",
            "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
            "time": "2026-10-23T16:00:00Z",
            "data": {
              "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
              "kind": "lsl.model.train",
              "status": "failed",
              "error": {
                "type": "https://example.invalid/problems/internal",
                "title": "Internal Server Error",
                "status": 500,
                "detail": "The job failed. The detail is a synthetic fixture."
              }
            }
          }
        ]
      },
      "ModelCandidateReadyEvent": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "title": "model.candidate_ready",
        "description": "Training produced a candidate model version.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "id",
          "time",
          "data"
        ],
        "properties": {
          "type": {
            "const": "model.candidate_ready"
          },
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Same value as the webhook-id header."
          },
          "time": {
            "type": "string",
            "format": "date-time",
            "description": "UTC time the event was emitted."
          },
          "data": {
            "type": "object",
            "additionalProperties": false,
            "description": "A model is ready for review.",
            "required": [
              "model_version_id",
              "eval_report_id",
              "status"
            ],
            "properties": {
              "model_version_id": {
                "type": "string",
                "format": "uuid",
                "description": "UUIDv7 of the candidate model."
              },
              "eval_report_id": {
                "type": "string",
                "format": "uuid",
                "description": "UUIDv7 of the evaluation report."
              },
              "status": {
                "const": "CANDIDATE"
              }
            }
          }
        },
        "examples": [
          {
            "type": "model.candidate_ready",
            "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
            "time": "2026-10-23T16:00:00Z",
            "data": {
              "model_version_id": "018bcfe5-6800-7000-8000-000000000006",
              "eval_report_id": "018bcfe5-6800-7000-8000-000000000008",
              "status": "CANDIDATE"
            }
          }
        ]
      },
      "ModelPromotedEvent": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "title": "model.promoted",
        "description": "An approver promoted a model version.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "id",
          "time",
          "data"
        ],
        "properties": {
          "type": {
            "const": "model.promoted"
          },
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Same value as the webhook-id header."
          },
          "time": {
            "type": "string",
            "format": "date-time",
            "description": "UTC time the event was emitted."
          },
          "data": {
            "type": "object",
            "additionalProperties": false,
            "description": "An approver promoted a model.",
            "required": [
              "model_version_id",
              "promoted_by",
              "promoted_at"
            ],
            "properties": {
              "model_version_id": {
                "type": "string",
                "format": "uuid",
                "description": "UUIDv7 of the promoted model."
              },
              "promoted_by": {
                "type": "string",
                "format": "uuid",
                "description": "UUIDv7 of the approver."
              },
              "promoted_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        },
        "examples": [
          {
            "type": "model.promoted",
            "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
            "time": "2026-10-23T16:00:00Z",
            "data": {
              "model_version_id": "018bcfe5-6800-7000-8000-000000000006",
              "promoted_by": "018bcfe5-6800-7000-8000-000000000001",
              "promoted_at": "2026-10-23T16:00:00Z"
            }
          }
        ]
      },
      "PredictionsUpdatedEvent": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "title": "predictions.updated",
        "description": "A scoring job wrote predictions.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "id",
          "time",
          "data"
        ],
        "properties": {
          "type": {
            "const": "predictions.updated"
          },
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Same value as the webhook-id header."
          },
          "time": {
            "type": "string",
            "format": "date-time",
            "description": "UTC time the event was emitted."
          },
          "data": {
            "type": "object",
            "additionalProperties": false,
            "description": "Stored predictions changed.",
            "required": [
              "model_version_id",
              "data_snapshot_id",
              "count"
            ],
            "properties": {
              "model_version_id": {
                "type": "string",
                "format": "uuid",
                "description": "UUIDv7 of the model that scored the lines."
              },
              "data_snapshot_id": {
                "type": "string",
                "format": "uuid",
                "description": "UUIDv7 of the snapshot."
              },
              "count": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        },
        "examples": [
          {
            "type": "predictions.updated",
            "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
            "time": "2026-10-23T16:00:00Z",
            "data": {
              "model_version_id": "018bcfe5-6800-7000-8000-000000000007",
              "data_snapshot_id": "018bcfe5-6800-7000-8000-000000000008",
              "count": 1
            }
          }
        ]
      },
      "InspectionPlanReadyEvent": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "title": "inspection_plan.ready",
        "description": "An inspection plan finished.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "id",
          "time",
          "data"
        ],
        "properties": {
          "type": {
            "const": "inspection_plan.ready"
          },
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Same value as the webhook-id header."
          },
          "time": {
            "type": "string",
            "format": "date-time",
            "description": "UTC time the event was emitted."
          },
          "data": {
            "type": "object",
            "additionalProperties": false,
            "description": "The inspection plan is ready to assign.",
            "required": [
              "plan"
            ],
            "properties": {
              "plan": {
                "$ref": "#/components/schemas/InspectionPlan"
              }
            }
          }
        },
        "examples": [
          {
            "type": "inspection_plan.ready",
            "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
            "time": "2026-10-23T16:00:00Z",
            "data": {
              "plan": {
                "budget_n": 1,
                "items": [
                  {
                    "expected_value": 0.3,
                    "inclusion_probability": 0.2,
                    "rank": 1,
                    "reason_code": "LEAD_LIKELY",
                    "service_line_id": "018bcfe5-6800-7000-8000-000000000008"
                  }
                ],
                "mode": "MIXED",
                "plan_id": "018bcfe5-6800-7000-8000-000000000007",
                "probability_share": 0.2,
                "schema_version": "2.1.0",
                "seed": 7
              }
            }
          }
        ]
      },
      "InspectionPlan": {
        "$defs": {
          "PlanItem": {
            "additionalProperties": false,
            "description": "One planned visit. inclusion_probability is required on every item.",
            "properties": {
              "expected_value": {
                "description": "Expected value of the visit.",
                "minimum": 0,
                "title": "Expected Value",
                "type": "number"
              },
              "inclusion_probability": {
                "description": "Inclusion probability in (0, 1].",
                "exclusiveMinimum": 0,
                "maximum": 1,
                "title": "Inclusion Probability",
                "type": "number"
              },
              "rank": {
                "description": "1-based rank.",
                "minimum": 1,
                "title": "Rank",
                "type": "integer"
              },
              "reason_code": {
                "description": "Uppercase reason code.",
                "pattern": "^[A-Z][A-Z0-9_]{0,63}$",
                "title": "Reason Code",
                "type": "string"
              },
              "service_line_id": {
                "description": "UUIDv7 of the service line.",
                "format": "uuid",
                "title": "Service Line Id",
                "type": "string"
              }
            },
            "required": [
              "service_line_id",
              "rank",
              "reason_code",
              "inclusion_probability",
              "expected_value"
            ],
            "title": "PlanItem",
            "type": "object"
          },
          "PlanMode": {
            "enum": [
              "REPRESENTATIVE",
              "REPLACEMENT",
              "MIXED",
              "LCRI_VALIDATION"
            ],
            "title": "PlanMode",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "description": "A batch of visits. Ranks are 1..n in list order.",
        "examples": [
          {
            "budget_n": 1,
            "items": [
              {
                "expected_value": 0.3,
                "inclusion_probability": 0.2,
                "rank": 1,
                "reason_code": "LEAD_LIKELY",
                "service_line_id": "018bcfe5-6800-7000-8000-000000000008"
              }
            ],
            "mode": "MIXED",
            "plan_id": "018bcfe5-6800-7000-8000-000000000007",
            "probability_share": 0.2,
            "schema_version": "2.1.0",
            "seed": 7
          }
        ],
        "properties": {
          "budget_n": {
            "description": "Number of visits. Must equal the item count.",
            "maximum": 100000,
            "minimum": 1,
            "title": "Budget N",
            "type": "integer"
          },
          "items": {
            "description": "Planned visits.",
            "items": {
              "$ref": "#/components/schemas/InspectionPlan/$defs/PlanItem"
            },
            "title": "Items",
            "type": "array"
          },
          "mode": {
            "$ref": "#/components/schemas/InspectionPlan/$defs/PlanMode",
            "description": "REPRESENTATIVE, REPLACEMENT, MIXED, or LCRI_VALIDATION."
          },
          "plan_id": {
            "description": "UUIDv7 primary id.",
            "format": "uuid",
            "title": "Plan Id",
            "type": "string"
          },
          "probability_share": {
            "description": "Share of the batch drawn with known inclusion probabilities.",
            "maximum": 1,
            "minimum": 0,
            "title": "Probability Share",
            "type": "number"
          },
          "schema_version": {
            "default": "2.1.0",
            "description": "C1 schema version. This release writes 2.1.0. Readers accept 2.0.0 and 2.1.0. 2.1.0 is additive to 2.0.0.",
            "enum": [
              "2.0.0",
              "2.1.0"
            ],
            "title": "Schema Version",
            "type": "string"
          },
          "seed": {
            "description": "Seed for the draw.",
            "maximum": 9223372036854775807,
            "minimum": 0,
            "title": "Seed",
            "type": "integer"
          }
        },
        "required": [
          "plan_id",
          "mode",
          "budget_n",
          "probability_share",
          "items",
          "seed"
        ],
        "title": "InspectionPlan",
        "type": "object"
      },
      "VerificationContradictsModelEvent": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "title": "verification.contradicts_model",
        "description": "A field result contradicts a confident prediction. This is a safety signal.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "id",
          "time",
          "data"
        ],
        "properties": {
          "type": {
            "const": "verification.contradicts_model"
          },
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Same value as the webhook-id header."
          },
          "time": {
            "type": "string",
            "format": "date-time",
            "description": "UTC time the event was emitted."
          },
          "data": {
            "type": "object",
            "additionalProperties": false,
            "description": "A field result that contradicts a confident one-class prediction.",
            "required": [
              "verification",
              "prediction"
            ],
            "properties": {
              "verification": {
                "$ref": "#/components/schemas/Verification"
              },
              "prediction": {
                "$ref": "#/components/schemas/Prediction"
              }
            }
          }
        },
        "examples": [
          {
            "type": "verification.contradicts_model",
            "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
            "time": "2026-10-23T16:00:00Z",
            "data": {
              "verification": {
                "method": "POTHOLE",
                "notes_text": "synthetic field note",
                "observed_at": "2024-06-15T12:00:00Z",
                "observed_material": "COPPER",
                "photo_refs": [
                  "synthetic/photos/3.bin"
                ],
                "schema_version": "2.1.0",
                "selection": {
                  "batch_id": null,
                  "design": "CUSTOMER_REQUEST",
                  "inclusion_probability": null
                },
                "service_line_id": "018bcfe5-6800-7000-8000-000000000004",
                "side": "UTILITY",
                "verification_detail": null,
                "verification_id": "018bcfe5-6800-7000-8000-000000000003"
              },
              "prediction": {
                "abstain": false,
                "alpha": 0.05,
                "conformal_set": [
                  "LEAD"
                ],
                "data_snapshot_id": "018bcfe5-6800-7000-8000-000000000008",
                "model_version_id": "018bcfe5-6800-7000-8000-000000000007",
                "p_grr": 0.1,
                "p_lead": 0.8,
                "p_non_lead": 0.1,
                "prediction_id": "018bcfe5-6800-7000-8000-000000000005",
                "schema_version": "2.1.0",
                "service_line_id": "018bcfe5-6800-7000-8000-000000000006",
                "top_factors": [
                  {
                    "contribution": -0.1,
                    "feature": "year_built"
                  }
                ]
              }
            }
          }
        ]
      },
      "ExportReadyEvent": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "title": "export.ready",
        "description": "An export file is ready.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "id",
          "time",
          "data"
        ],
        "properties": {
          "type": {
            "const": "export.ready"
          },
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Same value as the webhook-id header."
          },
          "time": {
            "type": "string",
            "format": "date-time",
            "description": "UTC time the event was emitted."
          },
          "data": {
            "type": "object",
            "additionalProperties": false,
            "description": "The export file is ready to download.",
            "required": [
              "job_id",
              "format",
              "href"
            ],
            "properties": {
              "job_id": {
                "type": "string",
                "format": "uuid",
                "description": "UUIDv7 of the export job."
              },
              "format": {
                "type": "string",
                "enum": [
                  "lcri_baseline",
                  "geojson",
                  "gpkg",
                  "csv",
                  "arcgis"
                ]
              },
              "href": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        },
        "examples": [
          {
            "type": "export.ready",
            "id": "msg_018bcfe5-6800-7000-8000-0000000000aa",
            "time": "2026-10-23T16:00:00Z",
            "data": {
              "job_id": "018bcfe5-6800-7000-8000-0000000000aa",
              "format": "csv",
              "href": "https://example.invalid/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
            }
          }
        ]
      },
      "Estimate": {
        "$defs": {
          "EstimateMethod": {
            "enum": [
              "MODEL_BASED",
              "DESIGN_BASED"
            ],
            "title": "EstimateMethod",
            "type": "string"
          },
          "EstimateScope": {
            "enum": [
              "SYSTEM",
              "TRACT",
              "BLOCK",
              "NEIGHBOURHOOD",
              "H3"
            ],
            "title": "EstimateScope",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "description": "A lead-count estimate with an interval. estimate_id and scope_key are added ids.",
        "examples": [
          {
            "estimate_id": "018bcfe5-6800-7000-8000-000000000008",
            "expected_lead": 3.5,
            "level": 0.9,
            "lower": 1.0,
            "method": "MODEL_BASED",
            "n_unknown": 10,
            "n_verified": 4,
            "schema_version": "2.1.0",
            "scope": "SYSTEM",
            "scope_key": null,
            "upper": 6.0
          }
        ],
        "properties": {
          "estimate_id": {
            "description": "UUIDv7 primary id. Added because section 4.1 names no id.",
            "format": "uuid",
            "title": "Estimate Id",
            "type": "string"
          },
          "expected_lead": {
            "description": "Expected lead count.",
            "minimum": 0,
            "title": "Expected Lead",
            "type": "number"
          },
          "level": {
            "description": "Interval level in (0, 1).",
            "exclusiveMaximum": 1,
            "exclusiveMinimum": 0,
            "title": "Level",
            "type": "number"
          },
          "lower": {
            "description": "Lower bound of the interval.",
            "minimum": 0,
            "title": "Lower",
            "type": "number"
          },
          "method": {
            "$ref": "#/components/schemas/Estimate/$defs/EstimateMethod",
            "description": "MODEL_BASED or DESIGN_BASED."
          },
          "n_unknown": {
            "description": "Unknown lines in the scope.",
            "minimum": 0,
            "title": "N Unknown",
            "type": "integer"
          },
          "n_verified": {
            "description": "Verified lines in the scope.",
            "minimum": 0,
            "title": "N Verified",
            "type": "integer"
          },
          "schema_version": {
            "default": "2.1.0",
            "description": "C1 schema version. This release writes 2.1.0. Readers accept 2.0.0 and 2.1.0. 2.1.0 is additive to 2.0.0.",
            "enum": [
              "2.0.0",
              "2.1.0"
            ],
            "title": "Schema Version",
            "type": "string"
          },
          "scope": {
            "$ref": "#/components/schemas/Estimate/$defs/EstimateScope",
            "description": "SYSTEM, TRACT, BLOCK, NEIGHBOURHOOD, or H3."
          },
          "scope_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Scope id. Null for SYSTEM. Tract uses an 11-digit GEOID.",
            "title": "Scope Key"
          },
          "upper": {
            "description": "Upper bound of the interval.",
            "minimum": 0,
            "title": "Upper",
            "type": "number"
          }
        },
        "required": [
          "estimate_id",
          "scope",
          "expected_lead",
          "lower",
          "upper",
          "level",
          "method",
          "n_verified",
          "n_unknown"
        ],
        "title": "Estimate",
        "type": "object"
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Required on every POST that creates a job or a record. The same key and the same body return the original result. A reused key with a different body returns 409. createApiKey and createWebhook replay the resource with the secret null; the secret is returned once. See draft-ietf-httpapi-idempotency-key-header-08.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255,
          "pattern": "^[A-Za-z0-9._:-]{1,255}$"
        }
      },
      "IfMatch": {
        "name": "If-Match",
        "in": "header",
        "required": true,
        "description": "RFC 9110 If-Match. Required when changing or deleting a resource.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "Opaque cursor returned as next_cursor. Omit it for the first page.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 512
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Page size. The default is 50 and the maximum is 100.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 50
        }
      },
      "WebhookId": {
        "name": "webhook-id",
        "in": "header",
        "required": true,
        "description": "Standard Webhooks message id.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        }
      },
      "WebhookTimestamp": {
        "name": "webhook-timestamp",
        "in": "header",
        "required": true,
        "description": "Standard Webhooks unix timestamp, in seconds.",
        "schema": {
          "type": "string",
          "pattern": "^[0-9]{1,20}$"
        }
      },
      "WebhookSignature": {
        "name": "webhook-signature",
        "in": "header",
        "required": true,
        "description": "Standard Webhooks HMAC-SHA256 signature. One or more v1 values.",
        "schema": {
          "type": "string",
          "minLength": 4
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad Request",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Bad Request",
                "value": {
                  "type": "https://example.invalid/problems/bad-request",
                  "title": "Bad Request",
                  "status": 400,
                  "detail": "The request is missing a required parameter or the body is not JSON.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Unauthorized",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          },
          "WWW-Authenticate": {
            "description": "RFC 6750 bearer challenge.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "Bearer realm=\"craftpine\""
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Unauthorized",
                "value": {
                  "type": "https://example.invalid/problems/unauthorized",
                  "title": "Unauthorized",
                  "status": 401,
                  "detail": "Send a bearer token or an X-API-Key.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Forbidden",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Forbidden",
                "value": {
                  "type": "https://example.invalid/problems/forbidden",
                  "title": "Forbidden",
                  "status": 403,
                  "detail": "The credential does not include the required scope.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Not Found",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Not Found",
                "value": {
                  "type": "https://example.invalid/problems/not-found",
                  "title": "Not Found",
                  "status": 404,
                  "detail": "No resource with that id exists in this tenant.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "Conflict": {
        "description": "Conflict",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Conflict",
                "value": {
                  "type": "https://example.invalid/problems/conflict",
                  "title": "Conflict",
                  "status": 409,
                  "detail": "The Idempotency-Key was reused with a different body.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "PreconditionFailed": {
        "description": "Precondition Failed",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Precondition Failed",
                "value": {
                  "type": "https://example.invalid/problems/precondition-failed",
                  "title": "Precondition Failed",
                  "status": 412,
                  "detail": "The If-Match tag does not match the current resource.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "ContentTooLarge": {
        "description": "Content Too Large",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Content Too Large",
                "value": {
                  "type": "https://example.invalid/problems/payload-too-large",
                  "title": "Content Too Large",
                  "status": 413,
                  "detail": "The body is larger than the configured limit.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "Unsupported Media Type",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Unsupported Media Type",
                "value": {
                  "type": "https://example.invalid/problems/unsupported-media-type",
                  "title": "Unsupported Media Type",
                  "status": 415,
                  "detail": "Send application/json.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "UnprocessableContent": {
        "description": "Unprocessable Content",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Unprocessable Content",
                "value": {
                  "type": "https://example.invalid/problems/unprocessable-content",
                  "title": "Unprocessable Content",
                  "status": 422,
                  "detail": "The body failed schema validation.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "PreconditionRequired": {
        "description": "Precondition Required",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Precondition Required",
                "value": {
                  "type": "https://example.invalid/problems/precondition-required",
                  "title": "Precondition Required",
                  "status": 428,
                  "detail": "If-Match is required on this operation.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Too Many Requests",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Too Many Requests",
                "value": {
                  "type": "https://example.invalid/problems/too-many-requests",
                  "title": "Too Many Requests",
                  "status": 429,
                  "detail": "The rate limit is exhausted.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Internal Server Error",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Internal Server Error",
                "value": {
                  "type": "https://example.invalid/problems/internal",
                  "title": "Internal Server Error",
                  "status": 500,
                  "detail": "The server failed while handling the request.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      },
      "NotImplemented": {
        "description": "Not Implemented",
        "headers": {
          "RateLimit-Policy": {
            "description": "Quota policy. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";q=60;w=60"
          },
          "RateLimit": {
            "description": "Remaining quota. See draft-ietf-httpapi-ratelimit-headers-11.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "\"default\";r=59;t=60"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sample": {
                "summary": "Not Implemented",
                "value": {
                  "type": "https://example.invalid/problems/not-implemented",
                  "title": "Not Implemented",
                  "status": 501,
                  "detail": "This operation is specified and not implemented.",
                  "instance": "/v1/jobs/018bcfe5-6800-7000-8000-0000000000aa"
                }
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "oidc": {
        "type": "openIdConnect",
        "openIdConnectUrl": "https://idp.example.invalid/realms/craftpine/.well-known/openid-configuration",
        "description": "OpenID Connect access token for the authorization code flow with PKCE. Send it as Authorization: Bearer. The tenant is read from the token. The listed scope is required. admin satisfies every operation."
      },
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Tenant API key. The secret is shown once and stored only as a hash. Lookup uses the prefix. The key must include x-required-scopes or admin. The secret is never written to logs."
      }
    }
  }
}
