{
  "openapi": "3.1.0",
  "info": {
    "title": "WhiteMagic Receipt Verification API",
    "version": "0.3.3",
    "description": "Stateless verification of continuity-receipt bundles and anchors, revocation distribution, and signed verification receipts. Auth: Authorization: Bearer <key> or X-WM-Key. Keyless: /health, /info, /revocations/{issuer}, GET /anchors/{digest}, and MCP discovery methods. x402 payments accepted on keyed methods. Conformance referee: POST /conformance grades a verifier's submitted outputs over the pinned corpus. Responses that pass auth carry X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset (daily buckets, 00:00 UTC reset).",
    "license": {
      "name": "Apache-2.0",
      "identifier": "Apache-2.0"
    }
  },
  "servers": [
    {
      "url": "https://api.whitemagic.dev"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "operationId": "health",
        "summary": "Liveness",
        "security": [],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "const": true
                    }
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          }
        }
      }
    },
    "/info": {
      "get": {
        "operationId": "info",
        "summary": "Service metadata (specs, endpoints, receipt issuer)",
        "security": [],
        "responses": {
          "200": {
            "description": "service document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          }
        }
      }
    },
    "/verify": {
      "post": {
        "operationId": "verify",
        "summary": "Verify a receipt bundle (or a batch)",
        "parameters": [
          {
            "name": "require_anchor",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "Require anchors (missing -> PROVISIONAL)"
          },
          {
            "name": "receipt",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "Return a signed verification receipt"
          },
          {
            "name": "cache",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "Opt in to the in-memory digest->verdict cache (single-bundle requests; 15 min TTL)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/Bundle"
                  },
                  {
                    "type": "object",
                    "required": [
                      "bundle"
                    ],
                    "properties": {
                      "bundle": {
                        "$ref": "#/components/schemas/Bundle"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": [
                      "bundles"
                    ],
                    "properties": {
                      "bundles": {
                        "type": "array",
                        "maxItems": 50,
                        "items": {
                          "$ref": "#/components/schemas/Bundle"
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "verdict payload; ?receipt=1 adds a signed verification_receipt; ?cache=1 adds a cache object",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verdict"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "x402 payment required (challenge body)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "413": {
            "description": "body too large (max 1 MiB)"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/verify-receipt": {
      "post": {
        "operationId": "verifyReceipt",
        "summary": "Verify a verification receipt (signature + shape; optional digest and revocation checks)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/VerificationReceipt"
                  },
                  {
                    "type": "object",
                    "required": [
                      "receipt"
                    ],
                    "properties": {
                      "receipt": {
                        "$ref": "#/components/schemas/VerificationReceipt"
                      },
                      "bundle_bytes_b64": {
                        "type": "string",
                        "description": "Bundle JSON bytes (base64); parsed and canonically digested"
                      },
                      "bundle": {
                        "$ref": "#/components/schemas/Bundle"
                      },
                      "revocations": {
                        "type": "array",
                        "items": {
                          "type": "object"
                        },
                        "description": "Revocation statements for the receipt's issuer (opt-in key_revoked check)"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "validity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReceiptCheck"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/verify-anchor": {
      "post": {
        "operationId": "verifyAnchor",
        "summary": "Verify an OpenTimestamps detached proof against a digest and optional header(s)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "proof",
                  "digest"
                ],
                "properties": {
                  "proof": {
                    "type": "string",
                    "description": "base64 of the .ots detached proof"
                  },
                  "digest": {
                    "type": "string",
                    "pattern": "^(sha256:)?[0-9a-f]{64}$"
                  },
                  "headers": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string",
                      "description": "80-byte header hex"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "anchor status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnchorResult"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/anchors": {
      "post": {
        "operationId": "storeAnchor",
        "summary": "Store an OpenTimestamps proof for a digest (keyed)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "digest",
                  "proof"
                ],
                "properties": {
                  "digest": {
                    "type": "string",
                    "pattern": "^(sha256:)?[0-9a-f]{64}$"
                  },
                  "proof": {
                    "type": "string"
                  },
                  "note": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "stored",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "stored": {
                      "const": true
                    },
                    "digest": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/anchors/{digest}": {
      "get": {
        "operationId": "getAnchor",
        "summary": "Fetch a stored anchor proof (keyless, ETag-aware)",
        "parameters": [
          {
            "name": "digest",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "stored anchor document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          },
          "304": {
            "description": "not modified (If-None-Match)",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          },
          "404": {
            "description": "no stored anchor for this digest"
          }
        }
      }
    },
    "/revocations/{issuer}": {
      "get": {
        "operationId": "getRevocations",
        "summary": "Fetch the stored revocation document for an issuer (keyless, ETag-aware)",
        "parameters": [
          {
            "name": "issuer",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "revocation document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          },
          "304": {
            "description": "not modified (If-None-Match)",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          },
          "404": {
            "description": "no document for this issuer"
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "summary": "MCP surface (JSON-RPC: initialize, tools/list, tools/call)",
        "description": "Tools: verify_bundle, verify_anchor, get_revocations. Discovery methods are keyless; tools/call requires a key or x402 payment.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "properties": {
                  "jsonrpc": {
                    "const": "2.0"
                  },
                  "id": {},
                  "method": {
                    "type": "string"
                  },
                  "params": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "x402 payment required (challenge body)"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/conformance": {
      "post": {
        "operationId": "conformance",
        "summary": "Grade a verifier submission over the pinned corpus; return a signed conformance report",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "implementation",
                  "results"
                ],
                "properties": {
                  "implementation": {
                    "type": "object",
                    "required": [
                      "name"
                    ],
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "version": {
                        "type": "string"
                      },
                      "language": {
                        "type": "string"
                      },
                      "url": {
                        "type": "string"
                      }
                    }
                  },
                  "results": {
                    "type": "object",
                    "description": "One or both corpora: bundles {verdict, codes}, verification_receipts {valid, errors}."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "signed conformance report",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "x402 payment required (challenge body)"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "conformance corpus not deployed"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Evaluation or invoiced key (see /info and whitemagic.dev/contact)"
      },
      "wmKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-WM-Key"
      },
      "x402": {
        "type": "apiKey",
        "in": "header",
        "name": "X-PAYMENT",
        "description": "x402 v1 payment header (Base USDC); 402 challenge returns requirements"
      }
    },
    "schemas": {
      "Bundle": {
        "type": "object",
        "description": "A continuity-receipt bundle (spec 0.1/0.2/0.3)",
        "required": [
          "spec",
          "task_id",
          "receipts"
        ],
        "properties": {
          "spec": {
            "type": "string"
          },
          "task_id": {
            "type": "string"
          },
          "receipts": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "additionalProperties": true
      },
      "Verdict": {
        "type": "object",
        "required": [
          "verdict"
        ],
        "properties": {
          "verdict": {
            "type": "string",
            "enum": [
              "TRUSTED",
              "PROVISIONAL",
              "INSUFFICIENT_EVIDENCE",
              "UNTRUSTED"
            ]
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "detail": {
                  "type": "string"
                },
                "receipt_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "provisional_reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "insufficient_reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "summary": {
            "type": "object"
          },
          "verification_receipt": {
            "$ref": "#/components/schemas/VerificationReceipt"
          }
        }
      },
      "VerificationReceipt": {
        "type": "object",
        "description": "A signed record of a verification run: the full result (verdict, errors, reasons, summary) with offline-checkable consistency.",
        "required": [
          "kind",
          "version",
          "bundle_digest",
          "verdict",
          "error_codes",
          "errors",
          "provisional_reasons",
          "insufficient_reasons",
          "summary",
          "verified_at",
          "issuer",
          "sig"
        ],
        "properties": {
          "kind": {
            "const": "continuity-receipt-verification"
          },
          "version": {
            "const": 1
          },
          "bundle_digest": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$"
          },
          "verdict": {
            "enum": [
              "TRUSTED",
              "PROVISIONAL",
              "INSUFFICIENT_EVIDENCE",
              "UNTRUSTED"
            ]
          },
          "error_codes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "code"
              ],
              "properties": {
                "code": {
                  "type": "string"
                },
                "detail": {
                  "type": "string"
                },
                "receipt_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "provisional_reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "insufficient_reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "summary": {
            "type": "object"
          },
          "verified_at": {
            "type": "string"
          },
          "verifier": {
            "type": "object"
          },
          "issuer": {
            "type": "string"
          },
          "sig": {
            "type": "object",
            "required": [
              "alg",
              "key",
              "value"
            ]
          }
        }
      },
      "ReceiptCheck": {
        "type": "object",
        "required": [
          "valid",
          "errors"
        ],
        "properties": {
          "valid": {
            "type": "boolean"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "issuer": {
            "type": "string"
          },
          "verdict": {
            "type": "string"
          },
          "verified_at": {
            "type": "string"
          },
          "bundle_digest": {
            "type": "string"
          },
          "digest_match": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "AnchorResult": {
        "type": "object",
        "required": [
          "status",
          "code"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "verified",
              "unverified",
              "mismatch",
              "invalid"
            ]
          },
          "code": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          },
          "file_digest": {
            "type": "string"
          },
          "attestations": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "confirmed": {
            "type": [
              "object",
              "null"
            ]
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "invalid JSON or shape",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "missing or invalid key",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                },
                "hint": {
                  "type": "string"
                },
                "docs": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Daily cap reached (Retry-After: 86400; X-RateLimit-* report the bucket)",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                }
              }
            }
          }
        },
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        }
      }
    },
    "headers": {
      "X-RateLimit-Limit": {
        "description": "Daily request cap for the caller's bucket.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Requests left today after this one.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Reset": {
        "description": "Seconds until the daily cap resets (00:00 UTC).",
        "schema": {
          "type": "integer"
        }
      }
    }
  },
  "security": [
    {
      "bearerKey": []
    },
    {
      "wmKeyHeader": []
    },
    {
      "x402": []
    }
  ]
}
