{
  "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": "labelled verifying key for certificate signatures: \"<scheme>:<hex>\" (es256 = ECDSA P-256 compressed SEC1; ed25519 = raw)" },
                "key_custody": { "type": "string", "description": "where the signing key lives (e.g. AWS KMS; dev custody in non-production)" },
                "legacy_pubkeys": { "type": "array", "items": { "type": "string" }, "description": "retired labelled pubkeys still accepted by /v1/verify (spec §8 key rotation)" },
                "dev_ephemeral_key": { "type": "boolean" },
                "note": { "type": "string" }
              }
            } } }
          }
        }
      }
    },
    "/v1/algorithms": {
      "get": {
        "tags": ["onboarding"],
        "summary": "Algorithm catalogue: ids, input contracts, embedded test vectors",
        "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": "array", "description": "The published test vectors, embedded inline — the same fixtures the engine test suite and CLI re-runner check (vector_id, algorithm, description, input, expected_output)", "items": { "type": "object" } }
                  }
                } },
                "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}/entropy": {
      "post": {
        "tags": ["deals"],
        "summary": "Pin the drand beacon value (random.v1 only)",
        "description": "Once all reveals are in, the server fetches the deal's pre-declared drand round from the public League of Entropy beacon (quicknet), pins the value, computes the draw, and issues the certificate. Callers never supply the value, so nobody can choose entropy. Idempotent: repeat calls after COMPUTED report the result.",
        "operationId": "provideEntropy",
        "security": [{ "bearerAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/DealId" }],
        "responses": {
          "200": {
            "description": "Beacon value pinned; deal COMPUTED with result, or already-computed report.",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "deal_id": { "type": "string" },
                "state": { "type": "string" },
                "result": { "nullable": true, "type": "object" },
                "certificate_id": { "nullable": true, "type": "string" }
              }
            } } }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" },
          "502": { "$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: labelled signature (es256/ed25519) under the current or a published legacy key, 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": "\"<scheme>:<hex>\" (es256 or ed25519) 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": "\"<scheme>:<hex>\" — es256:<128 hex> (ECDSA P-256, raw r||s low-S; the KMS launch form) or ed25519:<128 hex> (pre-KMS dev certs)" }
        }
      }
    }
  }
}
