{
  "openapi": "3.1.0",
  "info": {
    "title": "PactVerity Receipt API",
    "version": "1.0.0-beta",
    "description": "Stateless deterministic receipt creation and verification. Caller-supplied evidence only; no custody, independent monitoring, oracle, persistence guarantee or settlement."
  },
  "servers": [
    { "url": "https://pactverity.com" }
  ],
  "paths": {
    "/api/v1": {
      "get": {
        "summary": "API descriptor",
        "responses": { "200": { "description": "API routes and deployment boundary" } }
      }
    },
    "/api/v1/health": {
      "get": {
        "summary": "Run current known-answer self-tests",
        "description": "A point-in-time receipt and simulator self-test, not uptime history or an SLA.",
        "responses": {
          "200": { "description": "Self-tests passed" },
          "503": { "description": "Self-test unavailable or failed" }
        }
      }
    },
    "/api/v1/receipts": {
      "post": {
        "summary": "Create a deterministic assurance receipt",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CreateReceiptRequest" }
            }
          }
        },
        "responses": {
          "200": { "description": "Receipt created from caller-supplied evidence" },
          "400": { "description": "Schema validation failed" },
          "413": { "description": "Body exceeds 32 KiB" },
          "415": { "description": "Unsupported media type or content encoding" }
        }
      }
    },
    "/api/v1/receipts/verify": {
      "post": {
        "summary": "Recompute and verify an assurance receipt",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "https://pactverity.com/specs/pactverity-assurance-receipt-v1.schema.json" }
            }
          }
        },
        "responses": {
          "200": { "description": "Receipt is self-consistent" },
          "413": { "description": "Body exceeds 100 KiB" },
          "415": { "description": "Unsupported media type or content encoding" },
          "422": { "description": "Receipt is not self-consistent" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "CreateReceiptRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["agreementId", "serviceName", "providerReference", "issuedAt", "criteria", "evidence"],
        "properties": {
          "agreementId": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$" },
          "serviceName": { "type": "string", "minLength": 1, "maxLength": 120 },
          "providerReference": { "type": "string", "minLength": 1, "maxLength": 120 },
          "buyerReference": { "type": "string", "maxLength": 120 },
          "issuedAt": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$" },
          "criteria": {
            "type": "object",
            "additionalProperties": false,
            "required": ["maxLatencyMs", "minUptimeBps", "maxFreshnessSeconds", "expectedOutputSha256"],
            "properties": {
              "maxLatencyMs": { "type": "integer", "minimum": 1, "maximum": 10000000 },
              "minUptimeBps": { "type": "integer", "minimum": 0, "maximum": 10000 },
              "maxFreshnessSeconds": { "type": "integer", "minimum": 0, "maximum": 31536000 },
              "expectedOutputSha256": { "type": "string", "pattern": "^$|^[0-9a-f]{64}$" }
            }
          },
          "evidence": {
            "type": "object",
            "additionalProperties": false,
            "required": ["measuredLatencyMs", "uptimeBps", "freshnessSeconds", "observedOutputSha256", "observedAt"],
            "properties": {
              "measuredLatencyMs": { "type": "integer", "minimum": 0, "maximum": 10000000 },
              "uptimeBps": { "type": "integer", "minimum": 0, "maximum": 10000 },
              "freshnessSeconds": { "type": "integer", "minimum": 0, "maximum": 31536000 },
              "observedOutputSha256": { "type": "string", "pattern": "^$|^[0-9a-f]{64}$" },
              "observedAt": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$" }
            }
          }
        }
      }
    }
  }
}
