{
  "openapi": "3.0.3",
  "info": {
    "title": "hc2-3-accept",
    "version": "1.0.0",
    "description": "Replayable pass/fail cards for a submitted HTTP transcript. Does not fetch the subject URL and does not store the response body. Price 0 USDC."
  },
  "paths": {
    "/api": { "get": { "summary": "Discovery", "responses": { "200": { "description": "Machine discovery" } } } },
    "/api/cards": {
      "get": { "summary": "List cards", "responses": { "200": { "description": "Page of card summaries" } } },
      "post": {
        "summary": "Create or replay a card. Signed ag3nt-req:v1.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["subject", "observed_at", "response", "checks"],
                "properties": {
                  "subject": { "type": "string", "minLength": 12, "maxLength": 300, "description": "https URL. No userinfo and no fragment." },
                  "observed_at": { "type": "string", "description": "UTC timestamp YYYY-MM-DDTHH:MM:SS[.mmm]Z." },
                  "note": { "type": "string", "minLength": 1, "maxLength": 160, "description": "Optional. No CR or LF. Included in the card id only when present." },
                  "response": {
                    "type": "object",
                    "required": ["status", "body"],
                    "properties": {
                      "status": { "type": "integer", "minimum": 100, "maximum": 599 },
                      "body": { "description": "Any JSON value. A string is scored as raw UTF-8. Every other value is scored as canonical JSON." }
                    }
                  },
                  "checks": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 8,
                    "items": {
                      "type": "object",
                      "required": ["op"],
                      "properties": {
                        "op": { "type": "string", "enum": ["status_eq", "json_eq", "json_type", "body_includes", "body_sha256"] },
                        "path": { "type": "string", "minLength": 1, "maxLength": 80, "description": "Required for json_eq and json_type. Dot-separated segments. A numeric segment indexes an array." },
                        "eq": { "description": "status_eq: integer 100..599. json_eq: null, boolean, finite number, or string up to 200 chars. body_sha256: 64 lowercase hex digits." },
                        "type": { "type": "string", "enum": ["string", "number", "boolean", "object", "array", "null"], "description": "Required for json_type." },
                        "text": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Required for body_includes. Searched in the body material." }
                      }
                    }
                  }
                }
              },
              "example": {
                "subject": "https://example.com/api/health",
                "observed_at": "2026-10-04T19:00:00Z",
                "response": { "status": 200, "body": { "ok": true, "items": [{ "id": "a" }] } },
                "checks": [
                  { "op": "status_eq", "eq": 200 },
                  { "op": "json_eq", "path": "ok", "eq": true },
                  { "op": "json_type", "path": "items", "type": "array" },
                  { "op": "json_eq", "path": "items.0.id", "eq": "a" },
                  { "op": "body_includes", "text": "\"ok\":true" },
                  { "op": "body_sha256", "eq": "0e69ee052a63bf09115f9ecb0fe9d9bfdcf1079aca618935d3a7a3ac3cfd5f78" }
                ]
              }
            }
          }
        },
        "responses": { "201": { "description": "Created" }, "200": { "description": "Replay of the same canonical transcript" }, "400": { "description": "Invalid" }, "401": { "description": "Signature required" } }
      }
    },
    "/api/cards/{id}": { "get": { "summary": "Read one card", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }], "responses": { "200": { "description": "Card" }, "404": { "description": "Missing" } } } },
    "/api/stats": { "get": { "summary": "Counters", "responses": { "200": { "description": "Counters" } } } },
    "/api/feedback": {
      "post": { "summary": "Signed feedback", "responses": { "201": { "description": "Stored" }, "401": { "description": "Signature required" } } },
      "get": { "summary": "Owner reads feedback", "responses": { "200": { "description": "Items" }, "403": { "description": "Owner only" } } }
    }
  }
}
