{
  "openapi": "3.1.0",
  "info": {
    "title": "TBV Agents API",
    "version": "0.3.0",
    "description": "Public TBV Agents read, quote, simulate, faucet, and operation-status API contract. Hosted mutating testnet execution must use explicit auth, idempotency, and signed receipts."
  },
  "servers": [
    { "url": "https://agents.babylonlabs.io", "description": "Requested hosted production surface" },
    { "url": "https://agents.babylonlabs.io", "description": "Babylon Labs hosted production alias" },
    { "url": "http://localhost:8787", "description": "Local development surface" }
  ],
  "security": [],
  "paths": {
    "/health": {
      "get": {
        "operationId": "getHealth",
        "responses": {
          "200": { "$ref": "#/components/responses/HealthResponse" }
        }
      }
    },
    "/networks": {
      "get": {
        "operationId": "getNetworks",
        "responses": {
          "200": { "$ref": "#/components/responses/NetworkListResponse" }
        }
      }
    },
    "/networks/{networkId}": {
      "get": {
        "operationId": "getNetwork",
        "parameters": [{ "$ref": "#/components/parameters/NetworkId" }],
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" },
          "404": { "$ref": "#/components/responses/ErrorResponse" }
        }
      }
    },
    "/protocol/params": {
      "get": {
        "operationId": "getProtocolParams",
        "parameters": [{ "$ref": "#/components/parameters/NetworkIdQuery" }],
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" },
          "400": { "$ref": "#/components/responses/ErrorResponse" }
        }
      }
    },
    "/wallets/capabilities": {
      "get": {
        "operationId": "getWalletCapabilities",
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" }
        }
      }
    },
    "/flows": {
      "get": {
        "operationId": "listFlows",
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" }
        }
      }
    },
    "/flows/{flowId}": {
      "get": {
        "operationId": "getFlow",
        "parameters": [{ "$ref": "#/components/parameters/FlowId" }],
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" },
          "404": { "$ref": "#/components/responses/ErrorResponse" }
        }
      }
    },
    "/quote/pegin": {
      "post": {
        "operationId": "quotePegin",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/PeginQuoteRequest" },
              "examples": {
                "default": { "value": { "networkId": "public-testnet", "amount": "0.01btc" } }
              }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/PeginQuoteResponse" },
          "400": { "$ref": "#/components/responses/ErrorResponse" }
        }
      }
    },
    "/simulate/flow": {
      "post": {
        "operationId": "simulateFlow",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/FlowSimulationRequest" },
              "examples": {
                "default": {
                  "value": {
                    "networkId": "public-testnet",
                    "flowId": "pegin-aave-borrow-repay-withdraw",
                    "amount": "0.01btc"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/FlowSimulationResponse" },
          "400": { "$ref": "#/components/responses/ErrorResponse" }
        }
      }
    },
    "/operations/{operationId}": {
      "get": {
        "operationId": "getOperationStatus",
        "parameters": [{ "$ref": "#/components/parameters/OperationId" }],
        "responses": {
          "200": { "$ref": "#/components/responses/OperationStatusResponse" },
          "404": { "$ref": "#/components/responses/ErrorResponse" }
        }
      }
    },
    "/operations": {
      "get": {
        "operationId": "listRecentOperations",
        "parameters": [
          { "name": "environment", "in": "query", "required": false, "schema": { "type": "string", "default": "public-testnet" } },
          { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 } }
        ],
        "responses": {
          "200": { "$ref": "#/components/responses/OperationListResponse" }
        }
      }
    },
    "/faucet/status": {
      "get": {
        "operationId": "getFaucetStatus",
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" }
        }
      }
    },
    "/faucet": {
      "get": {
        "operationId": "getFaucetIndex",
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" }
        }
      }
    },
    "/faucet/claim-plan": {
      "post": {
        "operationId": "buildFaucetClaimPlan",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/FaucetClaimPlanRequest" }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" },
          "400": { "$ref": "#/components/responses/ErrorResponse" }
        }
      }
    },
    "/faucet/policy": {
      "get": {
        "operationId": "getAgentFaucetPolicy",
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" }
        }
      }
    },
    "/faucet/quota": {
      "get": {
        "operationId": "getAgentFaucetQuota",
        "security": [{ "ScopedFaucetSecret": [] }],
        "parameters": [
          { "name": "agentId", "in": "query", "required": false, "schema": { "type": "string" } },
          { "name": "subject", "in": "query", "required": false, "schema": { "type": "string" } },
          { "name": "trustTier", "in": "query", "required": false, "schema": { "type": "string", "default": "public_developer" } }
        ],
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" },
          "401": { "$ref": "#/components/responses/ErrorResponse" }
        }
      }
    },
    "/faucet/vouchers": {
      "post": {
        "operationId": "requestAgentFaucetVoucher",
        "summary": "Request a flow-scoped agent faucet voucher",
        "security": [{ "ScopedFaucetSecret": [] }],
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/AgentFaucetVoucherRequest" }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" },
          "400": { "$ref": "#/components/responses/ErrorResponse" },
          "401": { "$ref": "#/components/responses/ErrorResponse" },
          "429": { "$ref": "#/components/responses/ErrorResponse" }
        }
      }
    },
    "/faucet/vouchers/{voucherId}/claim": {
      "post": {
        "operationId": "claimAgentFaucetVoucher",
        "summary": "Claim an issued agent faucet voucher",
        "security": [{ "ScopedFaucetSecret": [] }],
        "parameters": [
          { "name": "voucherId", "in": "path", "required": true, "schema": { "type": "string" } },
          { "$ref": "#/components/parameters/IdempotencyKey" }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "payoutMode": { "enum": ["dry-run"] }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" },
          "400": { "$ref": "#/components/responses/ErrorResponse" },
          "401": { "$ref": "#/components/responses/ErrorResponse" },
          "409": { "$ref": "#/components/responses/ErrorResponse" },
          "429": { "$ref": "#/components/responses/ErrorResponse" }
        }
      }
    },
    "/faucet/receipts/{receiptId}": {
      "get": {
        "operationId": "getAgentFaucetReceipt",
        "parameters": [
          { "name": "receiptId", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" },
          "404": { "$ref": "#/components/responses/ErrorResponse" }
        }
      }
    },
    "/readiness": {
      "get": {
        "operationId": "getToolkitReadiness",
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" }
        }
      }
    },
    "/agent-artifacts": {
      "get": {
        "operationId": "getAgentArtifacts",
        "responses": {
          "200": { "$ref": "#/components/responses/GenericObjectResponse" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ScopedFaucetSecret": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Authorization credential configured server-side as token|agentId|subject|trustTier|scopes. Use tbv:testnet:faucet.request for voucher requests and tbv:testnet:faucet.claim for voucher claims and receipt lookup."
      }
    },
    "parameters": {
      "NetworkId": { "name": "networkId", "in": "path", "required": true, "schema": { "type": "string" } },
      "NetworkIdQuery": { "name": "networkId", "in": "query", "required": true, "schema": { "type": "string" } },
      "FlowId": { "name": "flowId", "in": "path", "required": true, "schema": { "type": "string" } },
      "OperationId": { "name": "operationId", "in": "path", "required": true, "schema": { "type": "string" } },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": { "type": "string", "minLength": 8, "maxLength": 128 },
        "description": "Client-generated key used to deduplicate mutating testnet requests."
      }
    },
    "headers": {
      "RateLimitLimit": { "schema": { "type": "integer" }, "description": "Request quota for the current window." },
      "RateLimitRemaining": { "schema": { "type": "integer" }, "description": "Remaining request quota for the current window." },
      "RateLimitReset": { "schema": { "type": "integer" }, "description": "Unix timestamp when the quota window resets." },
      "TraceId": { "schema": { "type": "string" }, "description": "Server trace id for support and audit." }
    },
    "schemas": {
      "Health": {
        "type": "object",
        "required": ["product", "status"],
        "properties": {
          "product": { "const": "tbv-agents" },
          "status": { "enum": ["ok", "degraded"] },
          "version": { "type": "string" }
        }
      },
      "Error": {
        "type": "object",
        "required": ["product", "error"],
        "properties": {
          "product": { "const": "tbv-agents" },
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": { "type": "string" },
              "message": { "type": "string" },
              "traceId": { "type": "string" }
            }
          }
        }
      },
      "GenericObject": {
        "type": "object",
        "required": ["product"],
        "additionalProperties": true,
        "properties": {
          "product": { "type": "string" },
          "command": { "type": "string" },
          "status": { "type": "string" }
        }
      },
      "PeginQuoteRequest": {
        "type": "object",
        "required": ["networkId", "amount"],
        "additionalProperties": false,
        "properties": {
          "networkId": { "type": "string" },
          "amount": { "type": "string", "pattern": "^[0-9]+(\\.[0-9]{1,8})?btc$" }
        }
      },
      "FlowSimulationRequest": {
        "type": "object",
        "required": ["networkId", "flowId"],
        "additionalProperties": false,
        "properties": {
          "networkId": { "type": "string" },
          "flowId": { "type": "string" },
          "amount": { "type": "string", "pattern": "^[0-9]+(\\.[0-9]{1,8})?btc$" }
        }
      },
      "FaucetClaimPlanRequest": {
        "type": "object",
        "required": ["signetAddress", "sepoliaAddress"],
        "additionalProperties": false,
        "properties": {
          "signetAddress": { "type": "string", "pattern": "^tb1[0-9a-zA-Z]{20,90}$" },
          "sepoliaAddress": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" },
          "btcAmount": { "type": "string" },
          "sepoliaEthAmount": { "type": "string" },
          "mockUsdcAmount": { "type": "string" },
          "voucher": { "type": "string" }
        }
      },
      "AgentFaucetVoucherRequest": {
        "type": "object",
        "required": ["agentId", "subject", "flowType", "operationId", "signetAddress", "sepoliaAddress", "walletProof"],
        "additionalProperties": false,
        "properties": {
          "agentId": { "type": "string" },
          "subject": { "type": "string" },
          "trustTier": { "enum": ["public_developer", "verified_agent", "partner_ci", "internal"] },
          "networkId": { "const": "public-testnet" },
          "flowType": { "enum": ["pegin_borrow", "repay_withdraw", "redeem", "vault_reorder", "full_testnet_flow"] },
          "operationId": { "type": "string" },
          "signetAddress": { "type": "string", "pattern": "^tb1[0-9a-zA-Z]{20,90}$" },
          "sepoliaAddress": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" },
          "walletProof": {
            "type": "string",
            "description": "Hosted production should use BIP-322/EIP-191 proof envelopes; local dry-run accepts an opaque proof reference."
          },
          "operationEvidence": {
            "type": "string",
            "description": "Hosted production should use an edge-verified operation entitlement attestation. Explicit local development mode may omit it."
          },
          "assets": {
            "type": "array",
            "items": { "enum": ["signet_btc", "sepolia_eth", "mock_usdc"] },
            "minItems": 1,
            "description": "Optional subset of the assets allowed by the selected flow."
          }
        }
      },
      "OperationAccepted": {
        "type": "object",
        "required": ["product", "operationId", "status"],
        "properties": {
          "product": { "const": "tbv-agents" },
          "operationId": { "type": "string" },
          "status": { "enum": ["accepted", "pending"] }
        }
      }
    },
    "responses": {
      "HealthResponse": { "description": "Health status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Health" } } } },
      "NetworkListResponse": { "description": "Network list", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GenericObject" } } } },
      "GenericObjectResponse": { "description": "Generic TBV Agents object", "headers": { "X-Trace-Id": { "$ref": "#/components/headers/TraceId" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GenericObject" } } } },
      "PeginQuoteResponse": { "description": "Peg-in quote", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GenericObject" } } } },
      "FlowSimulationResponse": { "description": "Simulation result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GenericObject" } } } },
      "OperationStatusResponse": { "description": "Operation status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GenericObject" } } } },
      "OperationListResponse": { "description": "Recent operation list", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GenericObject" } } } },
      "OperationAcceptedResponse": {
        "description": "Operation accepted",
        "headers": {
          "RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" },
          "RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" },
          "RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" },
          "X-Trace-Id": { "$ref": "#/components/headers/TraceId" }
        },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationAccepted" } } }
      },
      "ErrorResponse": { "description": "Error response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    }
  }
}
