{
  "openapi": "3.1.0",
  "info": {
    "title": "AffixIO Binary Eligibility Verification API",
    "description": "RESTful API for zero-knowledge proof based binary eligibility verification. Send an identifier and circuit ID, receive a cryptographically verified yes or no. No PII retention, no cookies, cryptographic proofs stored locally.",
    "version": "1.0.0",
    "contact": {
      "name": "AffixIO Support",
      "email": "hello@affix-io.com",
      "url": "https://affix-io.com"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://affix-io.com/terms/"
    }
  },
  "servers": [
    {
      "url": "https://api.affix-io.com/v1",
      "description": "Production environment",
      "variables": {}
    },
    {
      "url": "https://sandbox.api.affix-io.com/v1",
      "description": "Sandbox environment for testing"
    }
  ],
  "paths": {
    "/verify": {
      "post": {
        "summary": "Verify eligibility",
        "description": "Submit an identifier and circuit ID to receive a binary eligibility decision. Uses zero-knowledge proofs to verify eligibility without exposing underlying data. Response time typically 43ms average, max 500ms.",
        "operationId": "verify",
        "tags": ["Core"],
        "security": [
          {"api_key": []},
          {"bearer": []},
          {"mtls": []}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["identifier", "circuit_id"],
                "properties": {
                  "identifier": {
                    "type": "string",
                    "description": "Pseudonymised or hashed reference to verify. AffixIO does not validate format — the connected circuit resolves against relevant data source. Recommended: SHA-256 hex of raw identifier, salted client-side.",
                    "example": "3a7bd3e27785e7b7a6c0e7c1f4f3f6b8"
                  },
                  "circuit_id": {
                    "type": "string",
                    "description": "Circuit identifier from /circuits endpoint. Examples: health-age-verification, finance-kyc-verification, govt-voting-eligibility.",
                    "example": "health-age-verification"
                  },
                  "metadata": {
                    "type": "object",
                    "description": "Optional contextual metadata. Passed to circuit but never logged.",
                    "properties": {
                      "timestamp": {
                        "type": "integer",
                        "description": "Unix timestamp of verification request"
                      },
                      "source": {
                        "type": "string",
                        "description": "Client application identifier"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "eligible": {
                      "type": "boolean",
                      "description": "Binary eligibility result — true or false"
                    },
                    "circuit_id": {
                      "type": "string",
                      "description": "Circuit used for verification"
                    },
                    "token": {
                      "type": "string",
                      "description": "Optional signed JWT containing result proof. Include in subsequent requests to reference this verification.",
                      "nullable": true
                    },
                    "expires": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Expiration time of verification token (ISO 8601). Present if token is included.",
                      "nullable": true
                    },
                    "latency_ms": {
                      "type": "integer",
                      "description": "Milliseconds elapsed to complete verification"
                    },
                    "data_retained": {
                      "type": "null",
                      "description": "Always null — no PII or identifier data retained by AffixIO"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — missing or malformed parameters"
          },
          "401": {
            "description": "Unauthorized — invalid or missing authentication"
          },
          "404": {
            "description": "Circuit not found"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        }
      }
    },
    "/tokens/{id}/verify": {
      "get": {
        "summary": "Verify stored token",
        "description": "Re-verify a previously issued verification token without re-running the circuit. Useful for caching verification results across API calls.",
        "operationId": "verifyToken",
        "tags": ["Tokens"],
        "security": [
          {"api_key": []},
          {"bearer": []},
          {"mtls": []}
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "JWT token from previous /verify response",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Token valid",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "boolean",
                      "description": "Token validity status"
                    },
                    "eligible": {
                      "type": "boolean",
                      "description": "Original eligibility result"
                    },
                    "circuit_id": {
                      "type": "string"
                    },
                    "issued_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Token invalid or expired"
          }
        }
      }
    },
    "/circuits": {
      "get": {
        "summary": "List available circuits",
        "description": "Retrieve all available verification circuits. Each circuit verifies a specific eligibility criterion using cryptographic proofs.",
        "operationId": "listCircuits",
        "tags": ["Discovery"],
        "security": [
          {"api_key": []},
          {"bearer": []},
          {"mtls": []}
        ],
        "parameters": [
          {
            "name": "sector",
            "in": "query",
            "description": "Filter by sector (health, finance, government, education, motoring, travel, hospitality, entertainment, ticketing, cross-sector)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of available circuits",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "circuits": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "sector": {
                            "type": "string"
                          },
                          "input_methods": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Data source methods (API, Database, Blockchain, Government Registry, etc.)"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total circuits available"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "summary": "Health check",
        "description": "API health and status endpoint. No authentication required.",
        "operationId": "health",
        "tags": ["Status"],
        "responses": {
          "200": {
            "description": "Service healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": ["operational", "degraded", "offline"]
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "uptime_percent": {
                      "type": "number",
                      "description": "30-day uptime percentage"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/ticketking/proof-token": {
      "post": {
        "summary": "Issue revolving proof token",
        "description": "Issue a short-lived (e.g. 5s) proof token for a ticket. The ticketing circuit verifies eligibility (valid, paid, not cancelled). Token is one-time-use: first successful gate verify consumes it. Use to power QR/NFC that rotates to combat screenshot/replication fraud.",
        "operationId": "ticketkingIssueProofToken",
        "tags": ["TicketKing"],
        "security": [{"api_key": []}, {"bearer": []}, {"mtls": []}],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["ticket_id"],
                "properties": {
                  "ticket_id": {
                    "type": "string",
                    "description": "Ticket or order line identifier (resolved by ticketing circuit against eligibility data).",
                    "example": "TKT-a1b2c3d4"
                  },
                  "event_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Optional event scope."
                  },
                  "ttl_seconds": {
                    "type": "integer",
                    "default": 5,
                    "minimum": 1,
                    "maximum": 300,
                    "description": "Token lifetime in seconds (revolving window)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Proof token issued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "JWT proof token; present in QR or NFC payload for gate verify."
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "ticket_id": {"type": "string"},
                    "circuit_id": {"type": "string", "example": "ticketing"},
                    "eligible": {"type": "boolean"}
                  }
                }
              }
            }
          },
          "400": { "description": "Invalid request (e.g. invalid ticket_id or ttl)." },
          "403": { "description": "Ticket not eligible (cancelled, not paid, or not found)." },
          "401": { "description": "Unauthorized." },
          "429": { "description": "Rate limit exceeded." },
          "500": { "description": "Internal server error." }
        }
      }
    },
    "/api/ticketking/verify": {
      "post": {
        "summary": "Verify and consume proof token (gate)",
        "description": "Gate endpoint: validate the proof token (from QR/NFC) and consume it on first success. Rejects expired, already-consumed, or invalid tokens.",
        "operationId": "ticketkingVerify",
        "tags": ["TicketKing"],
        "security": [{"api_key": []}, {"bearer": []}, {"mtls": []}],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["token"],
                "properties": {
                  "token": {
                    "type": "string",
                    "description": "JWT proof token from attendee QR/NFC."
                  },
                  "gate_id": {
                    "type": "string",
                    "description": "Optional gate or lane identifier for audit."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token valid and consumed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accepted": { "type": "boolean", "example": true },
                    "ticket_id": { "type": "string" },
                    "consumed_at": { "type": "string", "format": "date-time" },
                    "gate_id": { "type": "string", "nullable": true }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing or malformed token." },
          "403": {
            "description": "Token rejected (expired, already consumed, or invalid).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accepted": { "type": "boolean", "example": false },
                    "reason": { "type": "string", "enum": ["expired", "already_consumed", "invalid", "ineligible"] }
                  }
                }
              }
            }
          },
          "401": { "description": "Unauthorized." },
          "500": { "description": "Internal server error." }
        }
      }
    },
    "/api/ticketking/circuit": {
      "get": {
        "summary": "Get ticketing circuit",
        "description": "Returns the ticketing circuit definition used by TicketKing (id, name, sector, input_methods).",
        "operationId": "ticketkingCircuit",
        "tags": ["TicketKing"],
        "security": [{"api_key": []}, {"bearer": []}, {"mtls": []}],
        "responses": {
          "200": {
            "description": "Ticketing circuit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": { "type": "string", "example": "ticketing" },
                    "name": { "type": "string" },
                    "description": { "type": "string" },
                    "sector": { "type": "string", "example": "ticketing" },
                    "input_methods": { "type": "array", "items": { "type": "string" } }
                  }
                }
              }
            }
          },
          "401": { "description": "Unauthorized." }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "api_key": {
        "type": "apiKey",
        "in": "header",
        "name": "X-AffixIO-Key",
        "description": "API key for server-to-server requests. Prefixed aio_live_ (production) or aio_test_ (sandbox)."
      },
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "OAuth 2.0 Bearer token obtained from POST /v1/auth/token"
      },
      "mtls": {
        "type": "mutualTLS",
        "description": "Mutual TLS certificate authentication for high-security environments"
      }
    }
  },
  "tags": [
    {
      "name": "Core",
      "description": "Primary verification endpoint"
    },
    {
      "name": "Tokens",
      "description": "Token verification and management"
    },
    {
      "name": "Discovery",
      "description": "Circuit discovery and listing"
    },
    {
      "name": "Status",
      "description": "Service health and status"
    },
    {
      "name": "TicketKing",
      "description": "Revolving ZK proof tickets for entry (anti-fraud)"
    }
  ]
}
