{
  "openapi": "3.1.0",
  "info": {
    "title": "Verifyum public proof API",
    "version": "2.0.0",
    "description": "Create and inspect privacy-preserving file commitments on Solana Mainnet. Public access requires no API key. Clients calculate the Verifyum commitment locally and never upload the original file, raw file hash, nonce, filename, or private manifest."
  },
  "servers": [
    {
      "url": "https://api.verifyum.com",
      "description": "Verifyum production API"
    }
  ],
  "externalDocs": {
    "description": "Verifyum agent guide",
    "url": "https://verifyum.com/docs/agent-api.md"
  },
  "security": [],
  "paths": {
    "/health": {
      "get": {
        "operationId": "getVerifyumHealth",
        "summary": "Read public service state",
        "responses": {
          "200": {
            "description": "Current public service state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          }
        }
      }
    },
    "/v2/anchor": {
      "post": {
        "operationId": "createVerifyumAnchor",
        "summary": "Queue one locally calculated Verifyum commitment",
        "description": "Send only the domain-separated Verifyum version 2 commitment. Do not send the source file or any private manifest field. Public clients must omit the Authorization header. Use one stable idempotency key for retries of the same commitment.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "https://verifyum.com/schema/anchor-request-v2.json"
              },
              "examples": {
                "publicAgentRequest": {
                  "summary": "Public agent request",
                  "value": {
                    "commitment": "sha256:8412d6863b2328c6a7ff94d49ec087b18b6fc2db0b60da8b8dea97d30ac0612b",
                    "idempotency_key": "agent-run-20260830-example-0001"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The proof is already in a terminal state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProofLifecycle"
                }
              }
            }
          },
          "202": {
            "description": "The commitment was accepted and is queued or submitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProofLifecycle"
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/ClientError" },
          "401": { "$ref": "#/components/responses/ClientError" },
          "409": { "$ref": "#/components/responses/ClientError" },
          "413": { "$ref": "#/components/responses/ClientError" },
          "415": { "$ref": "#/components/responses/ClientError" },
          "429": { "$ref": "#/components/responses/RetryableError" },
          "503": { "$ref": "#/components/responses/RetryableError" }
        }
      }
    },
    "/v2/proofs/{proofId}": {
      "get": {
        "operationId": "getVerifyumProofStatus",
        "summary": "Read one proof lifecycle state",
        "parameters": [
          {
            "name": "proofId",
            "in": "path",
            "required": true,
            "description": "A canonical 26-character Verifyum proof ID",
            "schema": { "$ref": "#/components/schemas/ProofId" }
          }
        ],
        "responses": {
          "200": {
            "description": "Current proof lifecycle state",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ProofLifecycle" }
              }
            }
          },
          "404": { "$ref": "#/components/responses/ClientError" },
          "503": { "$ref": "#/components/responses/RetryableError" }
        }
      }
    },
    "/v2/proofs/{proofId}/witnesses": {
      "get": {
        "operationId": "getVerifyumProofWitnessMembership",
        "summary": "Read optional Witness checkpoint membership",
        "description": "Returns an immutable proof-to-hourly-checkpoint Merkle membership when the Witness worker has published one. The caller must already know the proof ID; there is no listing operation. HTTP 404 means no supplemental membership is available and does not invalidate the Protocol v2 proof or Verifyum signature. This document does not by itself claim confirmation by OpenTimestamps, GitHub, Wayback, or Certificate Transparency.",
        "parameters": [
          {
            "name": "proofId",
            "in": "path",
            "required": true,
            "description": "A canonical 26-character Verifyum proof ID",
            "schema": { "$ref": "#/components/schemas/ProofId" }
          }
        ],
        "responses": {
          "200": {
            "description": "Immutable canonical Witness membership bundle",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "https://verifyum.com/schema/witness-proof-membership-v1.json"
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/ClientError" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ProofId": {
        "type": "string",
        "pattern": "^[0-7][0-9a-hjkmnp-tv-z]{25}$"
      },
      "Health": {
        "type": "object",
        "additionalProperties": false,
        "required": ["status", "service", "network", "anchoring", "access"],
        "properties": {
          "status": { "const": "ok" },
          "service": { "const": "verifyum-api" },
          "network": { "enum": ["devnet", "mainnet-beta"] },
          "anchoring": { "enum": ["enabled", "disabled"] },
          "access": { "enum": ["public", "authenticated", "closed"] }
        }
      },
      "ProofLifecycle": {
        "type": "object",
        "additionalProperties": true,
        "required": ["proof_id", "status", "network"],
        "properties": {
          "proof_id": { "$ref": "#/components/schemas/ProofId" },
          "status": { "enum": ["queued", "submitted", "finalized", "failed"] },
          "network": { "enum": ["devnet", "mainnet-beta"] },
          "proof_url": { "type": ["string", "null"], "format": "uri" },
          "status_url": { "type": ["string", "null"], "format": "uri" },
          "transaction_signature": { "type": ["string", "null"] },
          "failure_reason": { "type": "string" }
        }
      },
      "Error": {
        "type": "object",
        "additionalProperties": true,
        "required": ["error"],
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" }
        }
      }
    },
    "responses": {
      "ClientError": {
        "description": "The request is invalid, unauthorized, missing, or conflicts with an existing idempotency reservation",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "RetryableError": {
        "description": "The request is limited or the service is temporarily unavailable. Honor Retry-After when present.",
        "headers": {
          "Retry-After": {
            "schema": { "type": "string" }
          }
        },
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      }
    }
  }
}
