{
  "components": {
    "schemas": {
      "AlternativeSolutionSchema": {
        "description": "An alternative schedule solution.",
        "properties": {
          "assignments": {
            "items": {
              "$ref": "#/components/schemas/AssignmentSchema"
            },
            "title": "Assignments",
            "type": "array"
          },
          "objective_value": {
            "title": "Objective Value",
            "type": "number"
          },
          "solution_number": {
            "title": "Solution Number",
            "type": "integer"
          }
        },
        "required": [
          "solution_number",
          "assignments",
          "objective_value"
        ],
        "title": "AlternativeSolutionSchema",
        "type": "object"
      },
      "AssignmentSchema": {
        "description": "A single shift assignment.",
        "properties": {
          "date": {
            "title": "Date",
            "type": "string"
          },
          "employee_id": {
            "title": "Employee Id",
            "type": "string"
          },
          "shift_id": {
            "title": "Shift Id",
            "type": "string"
          }
        },
        "required": [
          "employee_id",
          "shift_id",
          "date"
        ],
        "title": "AssignmentSchema",
        "type": "object"
      },
      "BalanceResponse": {
        "description": "Current token balance of the caller's organization.",
        "properties": {
          "balance": {
            "title": "Balance",
            "type": "integer"
          }
        },
        "required": [
          "balance"
        ],
        "title": "BalanceResponse",
        "type": "object"
      },
      "ComponentHealth": {
        "description": "Health status of a component.",
        "properties": {
          "message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Message"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/HealthStatus"
          }
        },
        "required": [
          "name",
          "status"
        ],
        "title": "ComponentHealth",
        "type": "object"
      },
      "GenerationConfigSchema": {
        "description": "Configuration for schedule generation.",
        "properties": {
          "enabled_constraints": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "List of constraint names to enable (None = all)",
            "title": "Enabled Constraints"
          },
          "enabled_objectives": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "List of objective names to enable (None = all)",
            "title": "Enabled Objectives"
          },
          "max_solutions": {
            "default": 1,
            "description": "Number of alternative solutions to generate (1-5)",
            "maximum": 5.0,
            "minimum": 1.0,
            "title": "Max Solutions",
            "type": "integer"
          },
          "num_workers": {
            "default": 0,
            "description": "Number of solver threads (0 = auto)",
            "maximum": 16.0,
            "minimum": 0.0,
            "title": "Num Workers",
            "type": "integer"
          },
          "objective_weights": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "integer"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom weights for objectives",
            "title": "Objective Weights"
          },
          "timeout_seconds": {
            "default": 60,
            "description": "Maximum solving time in seconds (5-600)",
            "maximum": 600.0,
            "minimum": 5.0,
            "title": "Timeout Seconds",
            "type": "integer"
          }
        },
        "title": "GenerationConfigSchema",
        "type": "object"
      },
      "GenerationResultSchema": {
        "description": "Result of schedule generation.",
        "properties": {
          "alternative_solutions": {
            "items": {
              "$ref": "#/components/schemas/AlternativeSolutionSchema"
            },
            "title": "Alternative Solutions",
            "type": "array"
          },
          "assignments": {
            "items": {
              "$ref": "#/components/schemas/AssignmentSchema"
            },
            "title": "Assignments",
            "type": "array"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message"
          },
          "execution_time_seconds": {
            "title": "Execution Time Seconds",
            "type": "number"
          },
          "explanations": {
            "items": {
              "type": "string"
            },
            "title": "Explanations",
            "type": "array"
          },
          "input_summary": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Detailed summary of all input data for debugging and QA",
            "title": "Input Summary"
          },
          "rule_effectiveness": {
            "description": "Rules that never came into effect in this plan (Feature B2)",
            "items": {
              "$ref": "#/components/schemas/RuleEffectivenessSchema"
            },
            "title": "Rule Effectiveness",
            "type": "array"
          },
          "statistics": {
            "additionalProperties": true,
            "title": "Statistics",
            "type": "object"
          },
          "status": {
            "$ref": "#/components/schemas/SolverStatusResponse"
          },
          "success": {
            "title": "Success",
            "type": "boolean"
          },
          "unassigned_shifts": {
            "items": {
              "$ref": "#/components/schemas/UnassignedShiftSchema"
            },
            "title": "Unassigned Shifts",
            "type": "array"
          }
        },
        "required": [
          "success",
          "status",
          "execution_time_seconds"
        ],
        "title": "GenerationResultSchema",
        "type": "object"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "HealthResponse": {
        "description": "Health check response.",
        "properties": {
          "components": {
            "default": [],
            "items": {
              "$ref": "#/components/schemas/ComponentHealth"
            },
            "title": "Components",
            "type": "array"
          },
          "git_commit": {
            "default": "dev",
            "title": "Git Commit",
            "type": "string"
          },
          "service": {
            "title": "Service",
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/HealthStatus"
          },
          "timestamp": {
            "title": "Timestamp",
            "type": "string"
          },
          "version": {
            "title": "Version",
            "type": "string"
          }
        },
        "required": [
          "status",
          "service",
          "version",
          "timestamp"
        ],
        "title": "HealthResponse",
        "type": "object"
      },
      "HealthStatus": {
        "description": "Health status values.",
        "enum": [
          "healthy",
          "unhealthy",
          "degraded"
        ],
        "title": "HealthStatus",
        "type": "string"
      },
      "IssueTokenRequest": {
        "description": "Request to issue a new API token.",
        "properties": {
          "expires_in_days": {
            "anyOf": [
              {
                "maximum": 3650.0,
                "minimum": 1.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires In Days"
          },
          "label": {
            "default": "",
            "description": "Purpose, e.g. 'CI' or 'Zapier'",
            "maxLength": 100,
            "title": "Label",
            "type": "string"
          },
          "scopes": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Granted scopes; default ['solve:read', 'solve:write']",
            "title": "Scopes"
          },
          "test": {
            "default": false,
            "description": "Issue a vt_test_ sandbox token",
            "title": "Test",
            "type": "boolean"
          }
        },
        "title": "IssueTokenRequest",
        "type": "object"
      },
      "IssuedTokenResponse": {
        "description": "The ONLY response that ever contains the plaintext token.",
        "properties": {
          "expiresAt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expiresat"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "organizationId": {
            "title": "Organizationid",
            "type": "string"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "title": "Scopes",
            "type": "array"
          },
          "token": {
            "description": "Shown exactly once — store it now, it cannot be retrieved",
            "title": "Token",
            "type": "string"
          },
          "tokenId": {
            "title": "Tokenid",
            "type": "string"
          }
        },
        "required": [
          "token",
          "tokenId",
          "organizationId",
          "scopes",
          "label",
          "expiresAt"
        ],
        "title": "IssuedTokenResponse",
        "type": "object"
      },
      "ReadyResponse": {
        "description": "Readiness check response.",
        "properties": {
          "checks": {
            "additionalProperties": {
              "type": "boolean"
            },
            "title": "Checks",
            "type": "object"
          },
          "ready": {
            "title": "Ready",
            "type": "boolean"
          }
        },
        "required": [
          "ready",
          "checks"
        ],
        "title": "ReadyResponse",
        "type": "object"
      },
      "RevokeResponse": {
        "properties": {
          "revoked": {
            "title": "Revoked",
            "type": "boolean"
          },
          "tokenId": {
            "title": "Tokenid",
            "type": "string"
          }
        },
        "required": [
          "revoked",
          "tokenId"
        ],
        "title": "RevokeResponse",
        "type": "object"
      },
      "RuleEffectivenessSchema": {
        "description": "Per-rule verdict: did the rule come into effect in this plan? (Feature B2)",
        "properties": {
          "effective": {
            "title": "Effective",
            "type": "boolean"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "rule_id": {
            "title": "Rule Id",
            "type": "string"
          },
          "rule_name": {
            "title": "Rule Name",
            "type": "string"
          }
        },
        "required": [
          "rule_id",
          "rule_name",
          "effective"
        ],
        "title": "RuleEffectivenessSchema",
        "type": "object"
      },
      "SolveJobSummary": {
        "description": "Compact job entry for the tenant's job list.",
        "properties": {
          "completed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "job_id": {
            "title": "Job Id",
            "type": "string"
          },
          "result_available": {
            "default": false,
            "title": "Result Available",
            "type": "boolean"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tier"
          },
          "token_cost": {
            "default": 0,
            "title": "Token Cost",
            "type": "integer"
          }
        },
        "required": [
          "job_id",
          "status"
        ],
        "title": "SolveJobSummary",
        "type": "object"
      },
      "SolveListResponse": {
        "description": "A tenant's solve jobs (newest first).",
        "properties": {
          "jobs": {
            "items": {
              "$ref": "#/components/schemas/SolveJobSummary"
            },
            "title": "Jobs",
            "type": "array"
          }
        },
        "required": [
          "jobs"
        ],
        "title": "SolveListResponse",
        "type": "object"
      },
      "SolveRequest": {
        "description": "Self-contained solve request — all data travels in the payload, no server-side lookups.",
        "properties": {
          "area_groups": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Area groups (vigotime entity format)",
            "title": "Area Groups"
          },
          "availability": {
            "anyOf": [
              {
                "additionalProperties": {
                  "additionalProperties": {
                    "type": "boolean"
                  },
                  "type": "object"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Verfügbarkeit je Mitarbeiter und Datum: {employeeId: {'2026-09-01': true}}. false = an dem Tag nicht einsetzbar.",
            "title": "Availability"
          },
          "collective_agreements": {
            "anyOf": [
              {
                "additionalProperties": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Collective agreements (agreement_id -> agreement; vigotime entity format). Carries the FR-239 tariff working-time limits so a tariff-bound stateless solve enforces them (DEF-BRAVO-STATELESS-COLLECTIVE-AGREEMENT-01).",
            "title": "Collective Agreements"
          },
          "config": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/GenerationConfigSchema"
              },
              {
                "type": "null"
              }
            ],
            "description": "Solver configuration"
          },
          "department": {
            "additionalProperties": true,
            "description": "Department as JSON object in the vigotime entity format (camelCase)",
            "title": "Department",
            "type": "object"
          },
          "employee_boundary_week_hours": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "number"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Bereits gearbeitete Stunden in der ISO-Woche des Fensterstarts, VOR dem Start, je MA. Für die Wochenkappe der angeschnittenen Woche.",
            "title": "Employee Boundary Week Hours"
          },
          "employee_history": {
            "anyOf": [
              {
                "additionalProperties": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Gearbeitete Tage vor dem Fenster je MA (ISO-Daten). Für Folgetage- und datums-gekoppelte Regeln über die Plangrenze.",
            "title": "Employee History"
          },
          "employee_last_shift_end": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Endzeitpunkt der letzten Schicht vor dem Fenster je MA (ISO-Datetime, tz-aware empfohlen). Für die Mindestruhe am ersten Plantag.",
            "title": "Employee Last Shift End"
          },
          "employee_prior_night_run": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "integer"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Länge der am Vortag endenden Nachtserie je MA. Für Nachterholung über die Plangrenze.",
            "title": "Employee Prior Night Run"
          },
          "employees": {
            "description": "Employees as JSON objects in the vigotime entity format (camelCase)",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Employees",
            "type": "array"
          },
          "end_date": {
            "description": "Last day of the planning window (inclusive)",
            "format": "date",
            "title": "End Date",
            "type": "string"
          },
          "holiday_dates": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Feiertage als ISO-Datumsliste (z. B. ['2026-12-25']). Steuert holiday/isHoliday-Regeln; ohne Angabe gilt der eingebaute deutsche Feiertags-Superset.",
            "title": "Holiday Dates"
          },
          "hourly_rates": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "number"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-employee hourly rate",
            "title": "Hourly Rates"
          },
          "locked_assignments": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Vorbelegte/handgesetzte Schichten, die fix bleiben. Je Eintrag {employeeId, shiftDefinitionId, date}. Der Solver plant um sie herum.",
            "title": "Locked Assignments"
          },
          "planning_rules": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Planning rules (vigotime entity format)",
            "title": "Planning Rules"
          },
          "preferences": {
            "anyOf": [
              {
                "additionalProperties": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-employee preferences",
            "title": "Preferences"
          },
          "previous_assignments": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Zuweisungen des Vorplans (Stabilität/Replan): {employeeId, shiftId, date}. Der Solver bleibt möglichst nah daran (minimale Änderung).",
            "title": "Previous Assignments"
          },
          "qualifications": {
            "anyOf": [
              {
                "additionalProperties": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Employee qualifications (employee_id -> qualification ids); derived from employees if omitted",
            "title": "Qualifications"
          },
          "shifts": {
            "description": "Shift definitions as JSON objects in the vigotime entity format (camelCase)",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Shifts",
            "type": "array"
          },
          "sick_leaves": {
            "anyOf": [
              {
                "additionalProperties": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Sick-leave dates per employee",
            "title": "Sick Leaves"
          },
          "social_points": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "number"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Social-Points-GUTHABEN je Mitarbeiter: {employeeId: 100}. Die Punkte, die eine Person für Wunscherfüllungen 'ausgeben' kann. Überschreibt ein ggf. am Mitarbeiter gesetztes socialPoints-Feld. Zusammen mit wish_costs aktiv → weiches Budget: die Summe der gewährten Wunschkosten SOLL das Guthaben nicht übersteigen (Überschreitung = Strafe, nie unlösbar). Ohne wish_costs wirkungslos.",
            "title": "Social Points"
          },
          "soft_code_assignments": {
            "anyOf": [
              {
                "additionalProperties": {
                  "items": {
                    "additionalProperties": true,
                    "type": "object"
                  },
                  "type": "array"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Kürzel als weiche Vorgaben, gruppiert nach {'should': [...], 'may': [...]}. Je Eintrag {employeeId, date, ...}.",
            "title": "Soft Code Assignments"
          },
          "staffing_rules": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Staffing rules (vigotime entity format)",
            "title": "Staffing Rules"
          },
          "start_date": {
            "description": "First day of the planning window (inclusive)",
            "format": "date",
            "title": "Start Date",
            "type": "string"
          },
          "vacations": {
            "anyOf": [
              {
                "additionalProperties": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Vacation dates per employee",
            "title": "Vacations"
          },
          "webhook_secret": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional shared secret. If set, the webhook request carries an HMAC-SHA256 signature in the X-Vigotime-Signature header.",
            "title": "Webhook Secret"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional https URL that is POSTed once the solve finishes (completed or failed).",
            "title": "Webhook Url"
          },
          "wish_costs": {
            "anyOf": [
              {
                "additionalProperties": {
                  "additionalProperties": {
                    "type": "number"
                  },
                  "type": "object"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "KOSTEN (pointCost) einer Wunscherfüllung je Mitarbeiter und Datum: {employeeId: {'2026-09-03': 20}}. Der bezahlte Preis eines gewünschten freien Tages (z. B. baseCostPerDay × dayTypeMultiplier × priorityMultiplier). Wenn gesetzt, gewichtet der Solver das Honorieren PROPORTIONAL zum Preis (mehr bezahlt → stärker honoriert), statt nur nach grobem low/normal/high-Label. Speist zudem das Social-Points-Budget.",
            "title": "Wish Costs"
          },
          "wish_priorities": {
            "anyOf": [
              {
                "additionalProperties": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "type": "object"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Wunsch-Priorität je Mitarbeiter und Datum: {employeeId: {'2026-09-03': 'high'}}. low/normal/high → Gewicht 0.5/1.0/2.0 (Social-Points-Gewichtung).",
            "title": "Wish Priorities"
          },
          "wish_specs": {
            "anyOf": [
              {
                "additionalProperties": {
                  "items": {
                    "additionalProperties": true,
                    "type": "object"
                  },
                  "type": "array"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Differenzierte Wunsch-Spezifikationen je MA (z. B. Wochenend-Atomarität, Serien). Feinere Steuerung als die flache wishes-Map.",
            "title": "Wish Specs"
          },
          "wishes": {
            "anyOf": [
              {
                "additionalProperties": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Wished dates per employee",
            "title": "Wishes"
          },
          "workplace_duration_rules": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Workplace duration rules (vigotime entity format): target/covered duration per person at a workplace on the wp_assign axis. severity 'must' -> HARD bound, 'should' -> SOFT target. Omitted/empty -> inert (B0 Phase 3, Issue #57 Feature-2/B1).",
            "title": "Workplace Duration Rules"
          },
          "workplaces": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Workplaces (vigotime entity format)",
            "title": "Workplaces"
          }
        },
        "required": [
          "start_date",
          "end_date",
          "employees",
          "shifts",
          "department"
        ],
        "title": "SolveRequest",
        "type": "object"
      },
      "SolveStatsResponse": {
        "description": "Usage statistics for a tenant (basis for token-based pricing).",
        "properties": {
          "execution_time_seconds_total": {
            "title": "Execution Time Seconds Total",
            "type": "number"
          },
          "failed": {
            "title": "Failed",
            "type": "integer"
          },
          "in_progress": {
            "title": "In Progress",
            "type": "integer"
          },
          "solved": {
            "title": "Solved",
            "type": "integer"
          },
          "tokens_burned": {
            "title": "Tokens Burned",
            "type": "integer"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          },
          "unsolvable": {
            "title": "Unsolvable",
            "type": "integer"
          }
        },
        "required": [
          "total",
          "solved",
          "unsolvable",
          "failed",
          "in_progress",
          "tokens_burned",
          "execution_time_seconds_total"
        ],
        "title": "SolveStatsResponse",
        "type": "object"
      },
      "SolveStatusResponse": {
        "description": "Status of a stateless solve job (queryable during the run and after completion).",
        "properties": {
          "completed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message"
          },
          "input_summary": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Input Summary"
          },
          "job_id": {
            "title": "Job Id",
            "type": "string"
          },
          "progress": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Progress"
          },
          "result_available": {
            "default": false,
            "title": "Result Available",
            "type": "boolean"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tier"
          },
          "token_cost": {
            "default": 0,
            "title": "Token Cost",
            "type": "integer"
          },
          "webhook": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/WebhookStatus"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "job_id",
          "status"
        ],
        "title": "SolveStatusResponse",
        "type": "object"
      },
      "SolveSubmitResponse": {
        "description": "Response when a solve job is accepted.",
        "properties": {
          "job_id": {
            "title": "Job Id",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          }
        },
        "required": [
          "job_id",
          "status",
          "tier"
        ],
        "title": "SolveSubmitResponse",
        "type": "object"
      },
      "SolverStatusResponse": {
        "description": "Solver status for API responses.",
        "enum": [
          "optimal",
          "feasible",
          "infeasible",
          "unknown",
          "model_invalid",
          "timeout"
        ],
        "title": "SolverStatusResponse",
        "type": "string"
      },
      "TokenListEntry": {
        "description": "Token metadata — never a usable secret (the hash is only a revocation handle).",
        "properties": {
          "createdAt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Createdat"
          },
          "displayHint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Displayhint"
          },
          "expiresAt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expiresat"
          },
          "isTest": {
            "title": "Istest",
            "type": "boolean"
          },
          "label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Label"
          },
          "lastUsedAt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lastusedat"
          },
          "revokedAt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Revokedat"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "title": "Scopes",
            "type": "array"
          },
          "tokenId": {
            "title": "Tokenid",
            "type": "string"
          }
        },
        "required": [
          "tokenId",
          "displayHint",
          "label",
          "scopes",
          "isTest",
          "createdAt",
          "expiresAt",
          "revokedAt",
          "lastUsedAt"
        ],
        "title": "TokenListEntry",
        "type": "object"
      },
      "UnassignedShiftSchema": {
        "description": "Information about an unassigned shift.",
        "properties": {
          "date": {
            "title": "Date",
            "type": "string"
          },
          "details": {
            "additionalProperties": true,
            "title": "Details",
            "type": "object"
          },
          "reason": {
            "title": "Reason",
            "type": "string"
          },
          "shift_id": {
            "title": "Shift Id",
            "type": "string"
          }
        },
        "required": [
          "shift_id",
          "date",
          "reason"
        ],
        "title": "UnassignedShiftSchema",
        "type": "object"
      },
      "UsageRecord": {
        "description": "One billed operation — the receipt line.",
        "properties": {
          "at": {
            "title": "At",
            "type": "string"
          },
          "balanceAfter": {
            "title": "Balanceafter",
            "type": "integer"
          },
          "cost": {
            "title": "Cost",
            "type": "integer"
          },
          "metadata": {
            "additionalProperties": true,
            "title": "Metadata",
            "type": "object"
          },
          "operation": {
            "title": "Operation",
            "type": "string"
          },
          "reference": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reference"
          }
        },
        "required": [
          "at",
          "operation",
          "cost",
          "balanceAfter",
          "reference",
          "metadata"
        ],
        "title": "UsageRecord",
        "type": "object"
      },
      "UsageResponse": {
        "description": "The caller's usage ledger, newest first.",
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "records": {
            "items": {
              "$ref": "#/components/schemas/UsageRecord"
            },
            "title": "Records",
            "type": "array"
          }
        },
        "required": [
          "records",
          "count"
        ],
        "title": "UsageResponse",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      },
      "WebhookStatus": {
        "description": "Delivery state of the completion webhook.",
        "properties": {
          "attempts": {
            "default": 0,
            "title": "Attempts",
            "type": "integer"
          },
          "configured": {
            "default": false,
            "title": "Configured",
            "type": "boolean"
          },
          "delivered": {
            "default": false,
            "title": "Delivered",
            "type": "boolean"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "last_status_code": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Status Code"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          }
        },
        "title": "WebhookStatus",
        "type": "object"
      }
    }
  },
  "info": {
    "description": "The customer-facing surface: stateless solve jobs and API-token management. Authentication via X-API-Key (vt_live_/vt_test_ tokens).",
    "title": "vigotime Public API",
    "version": "0.1.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api/v1/account/balance": {
      "get": {
        "description": "Current token balance of the caller's organization.",
        "operationId": "get_balance_api_v1_account_balance_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BalanceResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get token balance",
        "tags": [
          "Account"
        ]
      }
    },
    "/api/v1/account/usage": {
      "get": {
        "description": "Append-only ledger of billed operations: when, what, how much, which job.\n\nEach record references the billed object (a solve's ``job_id``) and carries the balance\nright after the debit, so a bill can be reconstructed line by line.",
        "operationId": "get_usage_api_v1_account_usage_get",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List token usage",
        "tags": [
          "Account"
        ]
      }
    },
    "/api/v1/solve": {
      "get": {
        "description": "Returns the tenant's own solve jobs (newest first), persisted for 12 months. Multi-tenant: only the caller's jobs are returned.",
        "operationId": "list_solve_jobs_api_v1_solve_get",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SolveListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List the caller's solve jobs",
        "tags": [
          "Stateless Solve"
        ]
      },
      "post": {
        "description": "Accept a self-contained payload and start an async solve. Returns a job id to poll.",
        "operationId": "submit_solve_api_v1_solve_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SolveRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SolveSubmitResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Submit a stateless solve job",
        "tags": [
          "Stateless Solve"
        ]
      }
    },
    "/api/v1/solve/stats": {
      "get": {
        "description": "Aggregated usage of the caller's tenant: how many plans were solved/unsolvable/failed, tokens burned and total solver time. Basis for token-based pricing.",
        "operationId": "get_solve_stats_api_v1_solve_stats_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SolveStatsResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Usage statistics for the caller",
        "tags": [
          "Stateless Solve"
        ]
      }
    },
    "/api/v1/solve/{job_id}": {
      "get": {
        "description": "Returns the job status, live progress and webhook delivery state. Works during the run and after completion (persisted for 12 months).",
        "operationId": "get_solve_status_api_v1_solve__job_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "title": "Job Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SolveStatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get stateless solve job status",
        "tags": [
          "Stateless Solve"
        ]
      }
    },
    "/api/v1/solve/{job_id}/result": {
      "get": {
        "operationId": "get_solve_result_api_v1_solve__job_id__result_get",
        "parameters": [
          {
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "title": "Job Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerationResultSchema"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get stateless solve job result",
        "tags": [
          "Stateless Solve"
        ]
      }
    },
    "/api/v1/tokens": {
      "get": {
        "description": "List the organization's tokens — metadata only, never a usable secret.",
        "operationId": "list_tokens_api_v1_tokens_get",
        "parameters": [
          {
            "in": "header",
            "name": "x-user-id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-User-Id"
            }
          },
          {
            "in": "header",
            "name": "x-company-id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Company-Id"
            }
          },
          {
            "in": "header",
            "name": "x-department-id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Department-Id"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/TokenListEntry"
                  },
                  "title": "Response List Tokens Api V1 Tokens Get",
                  "type": "array"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List API tokens",
        "tags": [
          "API Tokens"
        ]
      },
      "post": {
        "description": "Issue a token for the caller's organization. The plaintext appears only here.",
        "operationId": "issue_token_api_v1_tokens_post",
        "parameters": [
          {
            "in": "header",
            "name": "x-user-id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-User-Id"
            }
          },
          {
            "in": "header",
            "name": "x-company-id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Company-Id"
            }
          },
          {
            "in": "header",
            "name": "x-department-id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Department-Id"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IssueTokenRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssuedTokenResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Issue API token",
        "tags": [
          "API Tokens"
        ]
      }
    },
    "/api/v1/tokens/{token_id}": {
      "delete": {
        "description": "Revoke a token of the caller's organization. Effective immediately.",
        "operationId": "revoke_token_api_v1_tokens__token_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "token_id",
            "required": true,
            "schema": {
              "title": "Token Id",
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "x-user-id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-User-Id"
            }
          },
          {
            "in": "header",
            "name": "x-company-id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Company-Id"
            }
          },
          {
            "in": "header",
            "name": "x-department-id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Department-Id"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevokeResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Revoke API token",
        "tags": [
          "API Tokens"
        ]
      }
    },
    "/health": {
      "get": {
        "description": "Basic health check endpoint.\n\nReturns basic service status. Used by container health checks\nand load balancers to determine if the service is alive.",
        "operationId": "health_check_health_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Health Check",
        "tags": [
          "Health"
        ]
      }
    },
    "/live": {
      "get": {
        "description": "Kubernetes liveness probe endpoint.\n\nSimple endpoint that returns 200 if the service is running.",
        "operationId": "liveness_check_live_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "title": "Response Liveness Check Live Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Liveness Check",
        "tags": [
          "Health"
        ]
      }
    },
    "/ready": {
      "get": {
        "description": "Readiness check endpoint.\n\nReturns whether the service is ready to accept traffic.\nChecks all required dependencies are available.",
        "operationId": "readiness_check_ready_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadyResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Readiness Check",
        "tags": [
          "Health"
        ]
      }
    }
  },
  "servers": [
    {
      "description": "Production",
      "url": "https://api.vigotime.com"
    }
  ]
}
