{
  "openapi": "3.1.0",
  "info": {
    "title": "Scudo Biometric API",
    "version": "1.0.0",
    "description": "Customer biometric endpoints. Obtain a fresh nonce for each plan operation. Challenges expire after 60 seconds. Sensor envelopes use the challenge_id and proof instead."
  },
  "servers": [
    {
      "url": "https://kinetiproof.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    },
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/v1/challenge": {
      "post": {
        "summary": "Issue a single-use, key-bound challenge",
        "operationId": "challenge",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful API response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Challenge"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credential or expired challenge",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "License restriction",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Challenge already spent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Quota exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/preflight": {
      "post": {
        "summary": "Run live plan preflight",
        "operationId": "preflight",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Session"
              },
              "example": {
                "nonce": "",
                "plan": {
                  "plan_type": "universal_scroll_v2",
                  "steps": [
                    {
                      "kind": "scroll",
                      "milliseconds": 1,
                      "pixels": 2
                    }
                  ],
                  "metrics": {
                    "net_pixels": 2,
                    "scroll_deltas": [
                      2
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful API response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verdict"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credential or expired challenge",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "License restriction",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Challenge already spent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Quota exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/audit-session": {
      "post": {
        "summary": "Audit a plan or sensor envelope",
        "operationId": "audit_session",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/Session"
                  },
                  {
                    "$ref": "#/components/schemas/Sensor"
                  }
                ]
              },
              "example": {
                "nonce": "",
                "plan": {
                  "plan_type": "universal_scroll_v2",
                  "steps": [
                    {
                      "kind": "scroll",
                      "milliseconds": 1,
                      "pixels": 2
                    }
                  ],
                  "metrics": {
                    "net_pixels": 2,
                    "scroll_deltas": [
                      2
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful API response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Audit"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credential or expired challenge",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "License restriction",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Challenge already spent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Quota exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/generate-certificate": {
      "post": {
        "summary": "Issue a signed certificate (Growth or Enterprise)",
        "operationId": "generate_certificate",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportRequest"
              },
              "example": {
                "nonce": "",
                "plan": {
                  "plan_type": "universal_scroll_v2",
                  "steps": [
                    {
                      "kind": "scroll",
                      "milliseconds": 1,
                      "pixels": 2
                    }
                  ],
                  "metrics": {
                    "net_pixels": 2,
                    "scroll_deltas": [
                      2
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful API response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Report"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credential or expired challenge",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "License restriction",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Challenge already spent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Quota exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/compare-sessions": {
      "post": {
        "summary": "Compare baseline and release (Growth or Enterprise)",
        "operationId": "compare_sessions",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompareRequest"
              },
              "example": {
                "nonce": "",
                "baseline": {
                  "plan_type": "universal_scroll_v2",
                  "steps": [
                    {
                      "kind": "scroll",
                      "milliseconds": 1,
                      "pixels": 2
                    }
                  ],
                  "metrics": {
                    "net_pixels": 2,
                    "scroll_deltas": [
                      2
                    ]
                  }
                },
                "release": {
                  "plan_type": "universal_scroll_v2",
                  "steps": [
                    {
                      "kind": "scroll",
                      "milliseconds": 1,
                      "pixels": 2
                    }
                  ],
                  "metrics": {
                    "net_pixels": 2,
                    "scroll_deltas": [
                      2
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful API response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Comparison"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credential or expired challenge",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "License restriction",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Challenge already spent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Quota exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      },
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    },
    "schemas": {
      "Plan": {
        "type": "object",
        "description": "Biometric session plan passed to the Scudo audit engine."
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      },
      "Challenge": {
        "type": "object",
        "properties": {
          "nonce": {
            "type": "string"
          },
          "challenge_id": {
            "type": "string"
          },
          "expires_in": {
            "type": "integer",
            "const": 60
          },
          "binding_key": {
            "type": "string"
          }
        },
        "required": [
          "nonce",
          "challenge_id",
          "expires_in",
          "binding_key"
        ]
      },
      "Session": {
        "type": "object",
        "properties": {
          "nonce": {
            "type": "string"
          },
          "plan": {
            "$ref": "#/components/schemas/Plan"
          }
        },
        "required": [
          "nonce",
          "plan"
        ]
      },
      "Sensor": {
        "type": "object",
        "properties": {
          "challenge_id": {
            "type": "string"
          },
          "payload": {
            "type": "string"
          },
          "proof": {
            "type": "string"
          }
        },
        "required": [
          "challenge_id",
          "payload",
          "proof"
        ],
        "additionalProperties": false
      },
      "ReportRequest": {
        "type": "object",
        "properties": {
          "nonce": {
            "type": "string"
          },
          "plan": {
            "$ref": "#/components/schemas/Plan"
          },
          "brand_name": {
            "type": "string"
          },
          "brand_color": {
            "type": "string"
          },
          "logo_svg_text": {
            "type": "string"
          },
          "client_name": {
            "type": "string"
          }
        },
        "required": [
          "nonce",
          "plan"
        ],
        "additionalProperties": false
      },
      "CompareRequest": {
        "type": "object",
        "properties": {
          "nonce": {
            "type": "string"
          },
          "baseline": {
            "$ref": "#/components/schemas/Plan"
          },
          "release": {
            "$ref": "#/components/schemas/Plan"
          },
          "brand_name": {
            "type": "string"
          },
          "brand_color": {
            "type": "string"
          },
          "logo_svg_text": {
            "type": "string"
          },
          "client_name": {
            "type": "string"
          }
        },
        "required": [
          "nonce",
          "baseline",
          "release"
        ],
        "additionalProperties": false
      },
      "Manifest": {
        "type": "object",
        "properties": {
          "algorithm": {
            "const": "RSA-SHA256"
          },
          "html_sha256": {
            "type": "string"
          },
          "data_sha256": {
            "type": "string"
          }
        },
        "required": [
          "algorithm",
          "html_sha256",
          "data_sha256"
        ]
      },
      "Envelope": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "description": "Biometric session plan passed to the Scudo audit engine."
          },
          "html": {
            "type": "string"
          },
          "manifest": {
            "$ref": "#/components/schemas/Manifest"
          },
          "public_key_pem": {
            "type": "string"
          },
          "signature": {
            "type": "string"
          }
        },
        "required": [
          "data",
          "html",
          "manifest",
          "public_key_pem",
          "signature"
        ]
      },
      "SignedPair": {
        "type": "object",
        "properties": {
          "html": {
            "type": "string"
          },
          "json": {
            "$ref": "#/components/schemas/Envelope"
          }
        },
        "required": [
          "html",
          "json"
        ]
      },
      "Verdict": {
        "type": "object",
        "properties": {
          "result": {
            "enum": [
              "PASS",
              "FAIL"
            ]
          },
          "diagnostics": {
            "type": "object"
          }
        },
        "required": [
          "result"
        ]
      },
      "Audit": {
        "type": "object",
        "properties": {
          "result": {
            "enum": [
              "PASS",
              "FAIL"
            ]
          },
          "diagnostics": {
            "type": "object"
          },
          "certificates": {
            "type": "object",
            "properties": {
              "html": {
                "type": "string"
              },
              "pdf_base64": {
                "type": "string"
              }
            },
            "required": [
              "html",
              "pdf_base64"
            ]
          },
          "level": {
            "type": "integer"
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "result"
        ]
      },
      "Report": {
        "type": "object",
        "properties": {
          "result": {
            "enum": [
              "PASS",
              "FAIL"
            ]
          },
          "diagnostics": {
            "type": "object"
          },
          "certificates": {
            "$ref": "#/components/schemas/SignedPair"
          }
        },
        "required": [
          "result"
        ]
      },
      "Comparison": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "comparison": {
                "$ref": "#/components/schemas/SignedPair"
              }
            },
            "required": [
              "comparison"
            ]
          },
          {
            "type": "object",
            "properties": {
              "result": {
                "const": "DETAILS_SUPPRESSED"
              }
            },
            "required": [
              "result"
            ]
          }
        ]
      }
    }
  }
}
