{
  "openapi": "3.0.3",
  "info": {
    "title": "Redeal API",
    "version": "0.1.0",
    "description": "Neutral computation escrow for agents. Parties commit to sealed inputs, Redeal runs a published deterministic algorithm, and issues a signed, transparency-logged certificate anyone can verify.\n\nQuickstart: POST /v1/keys -> POST /v1/deals -> each party POSTs commit then reveal with their invite token -> GET /v1/deals/{id}/certificate -> anyone GETs /v1/verify/{cert_id}.\n\nAgents: prefer the MCP server at /mcp (Streamable HTTP). See /llms.txt.",
    "license": { "name": "Apache-2.0" }
  },
  "servers": [
    { "url": "https://api.redeal.dev", "description": "production (planned)" },
    { "url": "http://localhost:8080", "description": "local dev" }
  ],
  "tags": [
    { "name": "onboarding" },
    { "name": "deals" },
    { "name": "certificates" },
    { "name": "transparency" }
  ],
  "paths": {
    "/v1/status": {
      "get": {
        "tags": ["onboarding"],
        "summary": "Service status and the deployment's certificate-signing pubkey",
        "operationId": "status",
        "responses": {
          "200": {
            "description": "Service status",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "status": { "type": "string", "example": "ok" },
                "service": { "type": "string", "example": "redeal" },
                "version": { "type": "string" },
                "pubkey": { "type": "string", "description": "hex Ed25519 verifying key for certificate signatures" },
                "dev_ephemeral_key": { "type": "boolean" },
                "note": { "type": "string" }
              }
            } } }
          }
        }
      }
    },
    "/v1/algorithms": {
      "get": {
        "tags": ["onboarding"],
        "summary": "Algorithm catalogue: ids, input contracts, test vector locations",
        "operationId": "listAlgorithms",
        "responses": {
          "200": {
            "description": "Catalogue of published algorithms and the commitment scheme",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "algorithms": { "type": "array", "items": {
                  "type": "object",
                  "properties": {
                    "id": { "type": "string", "enum": ["split.v1", "random.v1", "shapley.v1"] },
                    "name": { "type": "string" },
                    "parties": { "type": "string" },
                    "algorithm_params": { "type": "object" },
                    "party_input": { "type": "object" },
                    "test_vectors": { "type": "string" }
                  }
                } },
                "commitment": { "type": "string", "description": "sha256:<hex of sha256(JCS(party_input) ++ salt_bytes)>" },
                "protocol": { "type": "string" }
              }
            } } }
          }
        }
      }
    },
    "/v1/keys": {
      "post": {
        "tags": ["onboarding"],
        "summary": "Issue an API key (no signup, no email)",
        "operationId": "createKey",
        "description": "The key is shown once; only its hash is stored. Idempotent via the Idempotency-Key header.",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": {
          "201": {
            "description": "API key issued",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": { "api_key": { "type": "string", "example": "fp_a1b2..." } },
              "required": ["api_key"]
            } } }
          }
        }
      }
    },
    "/v1/deals": {
      "post": {
        "tags": ["deals"],
        "summary": "Create a deal and get one invite token per party",
        "operationId": "createDeal",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object",
          "properties": {
            "algorithm": { "type": "string", "enum": ["split.v1", "random.v1", "shapley.v1"] },
            "mode": { "type": "string", "enum": ["sealed", "open"], "default": "sealed" },
            "retention": { "type": "string", "enum": ["standard", "purge"], "default": "standard" },
            "party_labels": { "type": "array", "items": { "type": "string" }, "minItems": 2 },
            "commit_deadline": { "type": "integer", "description": "unix seconds UTC" },
            "reveal_deadline": { "type": "integer", "description": "unix seconds UTC" },
            "algorithm_params": { "type": "object", "description": "per-algorithm params; see GET /v1/algorithms" }
          },
          "required": ["algorithm", "party_labels", "commit_deadline", "reveal_deadline"]
        } } } },
        "responses": {
          "201": {
            "description": "Deal created. Invite tokens are shown ONCE and stored hashed.",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "deal_id": { "type": "string", "example": "d_9f2c..." },
                "state": { "type": "string", "example": "OPEN" },
                "invite_tokens": { "type": "array", "items": {
                  "type": "object",
                  "properties": {
                    "party": { "type": "integer" },
                    "label": { "type": "string" },
                    "token": { "type": "string" }
                  }
                } },
                "warning": { "type": "string" }
              },
              "required": ["deal_id", "state", "invite_tokens"]
            } } }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/deals/{id}": {
      "get": {
        "tags": ["deals"],
        "summary": "Deal view (never includes revealed inputs)",
        "operationId": "getDeal",
        "security": [{ "bearerAuth": [] }],
        "description": "Authenticate with the initiator API key or any party invite token.",
        "parameters": [{ "$ref": "#/components/parameters/DealId" }],
        "responses": {
          "200": {
            "description": "Deal view",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DealView" } } }
          },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "404": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/deals/{id}/commit": {
      "post": {
        "tags": ["deals"],
        "summary": "Commit a sealed input (party invite-token auth)",
        "operationId": "commitInput",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/DealId" }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object",
          "properties": {
            "commitment": { "type": "string", "description": "sha256:<hex of sha256(JCS(party_input) ++ salt_bytes)>" }
          },
          "required": ["commitment"]
        } } } },
        "responses": {
          "200": {
            "description": "Commitment recorded",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "deal_id": { "type": "string" },
                "state": { "type": "string" },
                "party": { "type": "integer" },
                "committed": { "type": "boolean" },
                "next": { "type": "string", "description": "instructive next step" }
              }
            } } }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/deals/{id}/reveal": {
      "post": {
        "tags": ["deals"],
        "summary": "Reveal an input against a prior commitment",
        "operationId": "revealInput",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/DealId" }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object",
          "properties": {
            "input": { "type": "object", "description": "the party_input for the deal's algorithm" },
            "salt": { "type": "string", "description": "the salt used in the commitment (default empty)" }
          },
          "required": ["input"]
        } } } },
        "responses": {
          "200": {
            "description": "Reveal accepted. When all parties reveal, the algorithm runs and the certificate is issued automatically.",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "deal_id": { "type": "string" },
                "state": { "type": "string" },
                "party": { "type": "integer" },
                "revealed": { "type": "boolean" },
                "result": { "nullable": true, "type": "object", "description": "populated once the deal COMPUTED" }
              }
            } } }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/deals/{id}/cancel": {
      "post": {
        "tags": ["deals"],
        "summary": "Cancel a deal (initiator only, before counterparties commit)",
        "operationId": "cancelDeal",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/DealId" }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": {
          "200": {
            "description": "Deal cancelled",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "deal_id": { "type": "string" },
                "state": { "type": "string", "example": "CANCELLED" }
              }
            } } }
          },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/deals/{id}/certificate": {
      "get": {
        "tags": ["certificates"],
        "summary": "Fetch the deal's certificate (parties only)",
        "operationId": "getCertificate",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/DealId" }],
        "responses": {
          "200": {
            "description": "The signed certificate with transparency-log inclusion proof",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Certificate" } } }
          },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error", "description": "CERT_NOT_READY / NO_CERTIFICATE — no certificate exists yet or ever" }
        }
      }
    },
    "/v1/verify/{cert_id}": {
      "get": {
        "tags": ["certificates"],
        "summary": "Public certificate verification (no auth, free)",
        "operationId": "verifyCertificate",
        "description": "Reports each check individually: Ed25519 signature, input_root well-formedness, Merkle inclusion against the transparency log.",
        "parameters": [{
          "name": "cert_id", "in": "path", "required": true,
          "schema": { "type": "string" }, "example": "c_4d8a..."
        }],
        "responses": {
          "200": {
            "description": "Verification report",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "cert_id": { "type": "string" },
                "valid": { "type": "boolean" },
                "outcome": { "type": "string", "enum": ["COMPUTED", "VOID"] },
                "checks": { "type": "object", "properties": {
                  "signature": { "type": "boolean" },
                  "input_root_wellformed": { "type": "boolean" },
                  "merkle_inclusion": { "type": "boolean" }
                } },
                "note": { "type": "string" }
              }
            } } }
          },
          "404": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/log/tree-head": {
      "get": {
        "tags": ["transparency"],
        "summary": "Signed transparency-log tree head",
        "operationId": "treeHead",
        "responses": {
          "200": {
            "description": "Current Merkle tree head, signed by the deployment key",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "tree_size": { "type": "integer" },
                "root_hash": { "type": "string" },
                "signature": { "type": "string", "description": "ed25519:<hex> over JCS({tree_size, root_hash})" }
              }
            } } }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key (fp_...) for initiator actions; invite token for party actions"
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key", "in": "header", "required": false,
        "schema": { "type": "string" },
        "description": "Stripe-style idempotency: replays the stored response for a repeated key + identical body; 409 on key reuse with a different body"
      },
      "DealId": {
        "name": "id", "in": "path", "required": true,
        "schema": { "type": "string" }, "example": "d_9f2c..."
      }
    },
    "responses": {
      "Error": {
        "description": "Error. The message is instructive: it names the code and the fix.",
        "content": { "application/json": { "schema": {
          "type": "object",
          "properties": { "error": { "type": "string", "example": "AUTH_REQUIRED: pass 'Authorization: Bearer <api_key>'; get a key via POST /v1/keys" } }
        } } }
      }
    },
    "schemas": {
      "DealView": {
        "type": "object",
        "description": "The deal view. NEVER contains revealed inputs.",
        "properties": {
          "deal_id": { "type": "string" },
          "algorithm": { "type": "string" },
          "algorithm_params": { "type": "object" },
          "mode": { "type": "string", "enum": ["sealed", "open"] },
          "retention": { "type": "string", "enum": ["standard", "purge"] },
          "state": { "type": "string", "enum": ["OPEN", "COMMITTING", "REVEALING", "COMPUTED", "CERTIFIED", "VOID", "EXPIRED", "CANCELLED"] },
          "initiator": { "type": "integer" },
          "parties": { "type": "array", "items": {
            "type": "object",
            "properties": {
              "index": { "type": "integer" },
              "label": { "type": "string" },
              "committed": { "type": "boolean" },
              "commitment": { "nullable": true, "type": "string" },
              "revealed": { "type": "boolean" }
            }
          } },
          "commit_deadline": { "type": "integer" },
          "reveal_deadline": { "type": "integer" },
          "created_at": { "type": "integer" },
          "commits_closed_at": { "nullable": true, "type": "integer" },
          "reveals_closed_at": { "nullable": true, "type": "integer" },
          "computed_at": { "nullable": true, "type": "integer" },
          "result": { "nullable": true, "type": "object" },
          "void_flakers": { "nullable": true, "type": "array", "items": { "type": "integer" } },
          "certificate_id": { "nullable": true, "type": "string" }
        }
      },
      "Certificate": {
        "type": "object",
        "description": "Signed outcome certificate (ADR-0004). signed-payload = JCS(cert minus signature and log_proof).",
        "properties": {
          "cert_version": { "type": "string", "example": "1" },
          "cert_id": { "type": "string" },
          "deal_id": { "type": "string" },
          "outcome": { "type": "string", "enum": ["COMPUTED", "VOID"] },
          "algorithm": { "type": "string" },
          "mode": { "type": "string", "enum": ["sealed", "open"] },
          "retention": { "type": "string", "enum": ["standard", "purge"] },
          "parties": { "type": "array", "items": {
            "type": "object",
            "properties": {
              "index": { "type": "integer" },
              "label": { "type": "string" },
              "commitment": { "nullable": true, "type": "string" },
              "attested_by": { "type": "string", "example": "deal_initiator" }
            }
          } },
          "input_root": { "nullable": true, "type": "string", "description": "Merkle root over the revealed inputs (null for VOID deals with insufficient reveals)" },
          "result": { "nullable": true, "type": "object" },
          "void_flakers": { "nullable": true, "type": "array", "items": { "type": "integer" } },
          "properties": { "type": "array", "items": { "type": "string" }, "description": "guarantee flags, e.g. verifiability" },
          "timing": { "type": "object", "properties": {
            "created_at": { "type": "integer" },
            "commits_closed_at": { "nullable": true, "type": "integer" },
            "reveals_closed_at": { "nullable": true, "type": "integer" },
            "computed_at": { "nullable": true, "type": "integer" }
          } },
          "log_proof": { "type": "object", "properties": {
            "tree_size": { "type": "integer" },
            "leaf_index": { "type": "integer" },
            "inclusion_path": { "type": "array", "items": { "type": "string" } }
          } },
          "tee_attestation": { "nullable": true, "type": "object", "description": "reserved; null until TEE deployments" },
          "signature": { "type": "string", "description": "ed25519:<hex>" }
        }
      }
    }
  }
}
