{
  "openapi": "3.1.0",
  "info": {
    "title": "Prova API",
    "version": "2026-05-01",
    "summary": "Programmable infrastructure for modern trade credit.",
    "description": "REST API for invoice escrows, coverage, claims, and non-custodial settlement. Institutions configure their own underwriting and pricing; the API executes them and returns posted outcomes. Sensitive risk inputs are represented as sealed values and are never decrypted. This is a partial contract covering the resources documented at https://getprova.trade/documentation; the Sandbox runs on Arbitrum Sepolia testnet.",
    "contact": { "name": "Prova", "url": "https://getprova.trade/contact", "email": "docs@getprova.trade" }
  },
  "servers": [
    { "url": "https://api.sandbox.getprova.trade/v1", "description": "Sandbox (Arbitrum Sepolia testnet)" },
    { "url": "https://api.getprova.trade/v1", "description": "Production (enabled after independent audit and institutional onboarding)" }
  ],
  "security": [{ "oauth2": ["coverage:write", "escrows:write"] }],
  "tags": [
    { "name": "Authentication" },
    { "name": "Escrows" },
    { "name": "Coverage" },
    { "name": "Transactions" }
  ],
  "paths": {
    "/oauth/token": {
      "post": {
        "tags": ["Authentication"],
        "summary": "Exchange client credentials for an access token",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": ["grant_type"],
                "properties": {
                  "grant_type": { "type": "string", "enum": ["client_credentials"] },
                  "scope": { "type": "string", "example": "coverage:write escrows:write" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "An access token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": { "type": "string", "example": "prova_sandbox_at_9f4c2be7a1d0" },
                    "token_type": { "type": "string", "example": "Bearer" },
                    "expires_in": { "type": "integer", "example": 900 },
                    "scope": { "type": "string", "example": "coverage:write escrows:write" }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/escrows": {
      "post": {
        "tags": ["Escrows"],
        "summary": "Open an invoice-backed escrow",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }, { "$ref": "#/components/parameters/ProvaVersion" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["invoice_number", "amount", "currency"],
                "properties": {
                  "invoice_number": { "type": "string", "example": "INV-2043" },
                  "amount": { "type": "integer", "description": "Minor units.", "example": 48000 },
                  "currency": { "type": "string", "example": "USDC" },
                  "counterparty": { "type": "string", "example": "bp_7c21a1180f4a" }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created escrow.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Escrow" } } }
          },
          "400": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/coverage/quotes": {
      "post": {
        "tags": ["Coverage"],
        "summary": "Quote coverage against an invoice",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }, { "$ref": "#/components/parameters/ProvaVersion" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["invoice_id", "covered_pct"],
                "properties": {
                  "invoice_id": { "type": "string", "example": "esc_9f4c2be7a1d0" },
                  "covered_pct": { "type": "integer", "minimum": 1, "maximum": 100, "example": 90 },
                  "risk": { "$ref": "#/components/schemas/SealedRisk" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A coverage quote.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CoverageQuote" } } }
          },
          "422": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/coverage": {
      "post": {
        "tags": ["Coverage"],
        "summary": "Bind coverage from a quote",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["quote_id"],
                "properties": { "quote_id": { "type": "string", "example": "cvq_2be7a1d09f4c" } }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The bound coverage.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Coverage" } } }
          },
          "409": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/transactions": {
      "get": {
        "tags": ["Transactions"],
        "summary": "List ledger movements",
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "maximum": 100 } },
          { "name": "starting_after", "in": "query", "schema": { "type": "string" }, "description": "A cursor from a previous page's next_cursor." }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of transactions.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TransactionList" } } }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "oauth2": {
        "type": "oauth2",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://api.sandbox.getprova.trade/v1/oauth/token",
            "scopes": {
              "escrows:write": "Create and manage invoice escrows.",
              "coverage:write": "Quote and bind coverage.",
              "transactions:read": "Read ledger movements."
            }
          }
        }
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "schema": { "type": "string", "format": "uuid" },
        "description": "A unique key per logical operation. Retries with the same key replay the first response for 24h."
      },
      "ProvaVersion": {
        "name": "Prova-Version",
        "in": "header",
        "schema": { "type": "string", "example": "2026-05-01" },
        "description": "Pin a dated API release. Omitting it uses the account default."
      }
    },
    "responses": {
      "Error": {
        "description": "A structured error.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "schemas": {
      "SealedRisk": {
        "type": "object",
        "description": "Sealed risk handles produced by the SDK before they reach the API. Prova computes on them without decrypting.",
        "properties": {
          "credit_score": { "type": "string", "example": "enc:0x9f4c…" },
          "credit_limit": { "type": "string", "example": "enc:0x2be7…" },
          "exposure": { "type": "string", "example": "enc:0x1a08…" }
        }
      },
      "Escrow": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "esc_9f4c2be7a1d0" },
          "object": { "type": "string", "example": "escrow" },
          "invoice_number": { "type": "string", "example": "INV-2043" },
          "amount": { "type": "integer", "example": 48000 },
          "currency": { "type": "string", "example": "USDC" },
          "status": { "type": "string", "enum": ["open", "covered", "settled", "closed"], "example": "open" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "CoverageQuote": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "cvq_2be7a1d09f4c" },
          "object": { "type": "string", "example": "coverage_quote" },
          "invoice_id": { "type": "string", "example": "esc_9f4c2be7a1d0" },
          "covered_pct": { "type": "integer", "example": 90 },
          "premium_bps": { "type": "integer", "example": 200 },
          "currency": { "type": "string", "example": "USDC" },
          "status": { "type": "string", "enum": ["quoted", "expired"], "example": "quoted" },
          "expires_at": { "type": "string", "format": "date-time" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "Coverage": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "cov_2be7a1d09f4c" },
          "object": { "type": "string", "example": "coverage" },
          "invoice_id": { "type": "string", "example": "esc_9f4c2be7a1d0" },
          "covered_pct": { "type": "integer", "example": 90 },
          "premium_bps": { "type": "integer", "example": 200 },
          "status": { "type": "string", "enum": ["bound", "claimed", "settled", "cancelled"], "example": "bound" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "Transaction": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "txn_1a08c7b6a5e2" },
          "type": { "type": "string", "enum": ["premium", "settlement", "fee", "claim_payout"], "example": "premium" },
          "amount": { "type": "integer", "example": 960 },
          "currency": { "type": "string", "example": "USDC" },
          "coverage_id": { "type": "string", "example": "cov_2be7a1d09f4c" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "TransactionList": {
        "type": "object",
        "properties": {
          "object": { "type": "string", "example": "list" },
          "url": { "type": "string", "example": "/v1/transactions" },
          "has_more": { "type": "boolean", "example": true },
          "next_cursor": { "type": "string", "nullable": true, "example": "txn_1a08c7b6a5e2" },
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Transaction" } }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": { "type": "string", "example": "invalid_request_error" },
              "code": { "type": "string", "example": "covered_pct_out_of_range" },
              "message": { "type": "string", "example": "covered_pct must be between 1 and 100." },
              "param": { "type": "string", "example": "covered_pct" },
              "request_id": { "type": "string", "example": "req_5e21a3d0c7b6" }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "event": {
      "post": {
        "summary": "Signed lifecycle event delivered to your endpoint",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": { "type": "string", "example": "evt_7c21a1180f4a" },
                  "object": { "type": "string", "example": "event" },
                  "type": {
                    "type": "string",
                    "enum": ["escrow.created", "coverage.quoted", "coverage.bound", "claim.opened", "claim.resolved", "settlement.completed"],
                    "example": "coverage.bound"
                  },
                  "created_at": { "type": "string", "format": "date-time" },
                  "data": { "type": "object", "properties": { "object": { "type": "object" } } }
                }
              }
            }
          }
        },
        "responses": { "2XX": { "description": "Acknowledged within 10 seconds." } }
      }
    }
  }
}
