{
  "openapi": "3.1.0",
  "info": {
    "title": "Noetfield ABCP Gateway",
    "description": "Vendor-readable OpenAPI for the Agentic Banking Control Plane. Live money requires mTLS or bearer service tokens against a private deployment — this Worker publishes doctrine, schemas, and verification examples only. Partner rails move value; ABCP assures.",
    "version": "2.4",
    "contact": {
      "email": "operations@noetfield.com",
      "url": "https://banking.noetfield.com"
    }
  },
  "servers": [
    {
      "url": "https://banking.noetfield.com",
      "description": "Public doctrine + receipt verify example (no live money)"
    },
    {
      "url": "https://abcp.example.internal",
      "description": "Customer private gateway (live; auth required)"
    }
  ],
  "x-abcp-error-codes": [
    {
      "code": "AUTH_INVALID",
      "http": 401,
      "meaning": "Caller authentication failed"
    },
    {
      "code": "AGENT_INACTIVE",
      "http": 403,
      "meaning": "Agent suspended or not provisioned"
    },
    {
      "code": "TOOL_NOT_ALLOWED",
      "http": 403,
      "meaning": "Tool not on agent allowlist"
    },
    {
      "code": "SCHEMA_INVALID",
      "http": 400,
      "meaning": "Arguments failed JSON Schema"
    },
    {
      "code": "SCOPE_VIOLATION",
      "http": 403,
      "meaning": "Tenant or principal scope mismatch"
    },
    {
      "code": "LIMIT_TX",
      "http": 403,
      "meaning": "Per-transaction amount over policy"
    },
    {
      "code": "LIMIT_DAILY",
      "http": 403,
      "meaning": "Daily spend cap exceeded"
    },
    {
      "code": "LIMIT_LOOP",
      "http": 403,
      "meaning": "Tool-call loop budget exceeded"
    },
    {
      "code": "CONFIRM_REQUIRED",
      "http": 403,
      "meaning": "High-impact action needs confirm token"
    },
    {
      "code": "CONFIRM_INVALID",
      "http": 403,
      "meaning": "Confirm missing, expired, or replayed"
    },
    {
      "code": "DESTINATION_BLOCKED",
      "http": 403,
      "meaning": "Destination fails policy allow/deny"
    },
    {
      "code": "RAIL_TRANSPORT",
      "http": 502,
      "meaning": "Partner rail transport failure"
    },
    {
      "code": "RAIL_DECLINED",
      "http": 403,
      "meaning": "Partner declined the transfer"
    },
    {
      "code": "RAIL_PENDING",
      "http": 202,
      "meaning": "Partner accepted; settlement pending"
    },
    {
      "code": "DLP_BLOCK",
      "http": 403,
      "meaning": "Sensitive data would leave the boundary"
    },
    {
      "code": "IDEMPOTENCY_CONFLICT",
      "http": 409,
      "meaning": "Same key, different payload"
    },
    {
      "code": "SIGNATURE_INVALID",
      "http": 400,
      "meaning": "Receipt signature verification failed"
    },
    {
      "code": "NOT_FOUND",
      "http": 404,
      "meaning": "Resource does not exist"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerServiceToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "Required for live ABCP gateway calls. Not accepted on this marketing Worker."
      },
      "MutualTLS": {
        "type": "mutualTLS",
        "description": "Preferred for bank/fintech production. Required for live; not implemented on this Worker."
      }
    },
    "schemas": {
      "ToolCallRequest": {
        "type": "object",
        "required": [
          "agent_id",
          "tenant_id",
          "tool",
          "arguments",
          "idempotency_key"
        ],
        "additionalProperties": false,
        "properties": {
          "agent_id": {
            "type": "string"
          },
          "tenant_id": {
            "type": "string"
          },
          "tool": {
            "type": "string",
            "enum": [
              "get_balance",
              "list_transactions",
              "create_payment",
              "create_card_auth_hold",
              "cancel_pending_payment",
              "revoke_agent"
            ]
          },
          "arguments": {
            "type": "object",
            "additionalProperties": true
          },
          "idempotency_key": {
            "type": "string"
          },
          "confirm_token": {
            "type": [
              "string",
              "null"
            ]
          },
          "client_request_id": {
            "type": "string"
          }
        }
      },
      "ReceiptMoneyV1": {
        "$ref": "https://banking.noetfield.com/schema/receipt-money-v1.json"
      },
      "ErrorBody": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "receipt_id": {
            "type": "string"
          }
        }
      },
      "VerifyRequest": {
        "type": "object",
        "required": [
          "payload",
          "signature_b64"
        ],
        "properties": {
          "payload": {
            "type": "object"
          },
          "signature_b64": {
            "type": "string",
            "description": "Ed25519 signature over canonical JSON of payload"
          }
        }
      }
    },
    "responses": {
      "AuthInvalid": {
        "description": "AUTH_INVALID",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorBody"
            }
          }
        }
      },
      "ForbiddenPolicy": {
        "description": "Policy rejection (see x-abcp-error-codes)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorBody"
            }
          }
        }
      },
      "RailTransport": {
        "description": "RAIL_TRANSPORT",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorBody"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/v1/tools/call": {
      "post": {
        "summary": "Invoke an allowlisted money tool through ABCP",
        "security": [
          {
            "BearerServiceToken": []
          },
          {
            "MutualTLS": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ToolCallRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "accepted or idempotent replay"
          },
          "202": {
            "description": "pending rail settlement",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "400": {
            "description": "SCHEMA_INVALID"
          },
          "401": {
            "$ref": "#/components/responses/AuthInvalid"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenPolicy"
          },
          "409": {
            "description": "IDEMPOTENCY_CONFLICT"
          },
          "502": {
            "$ref": "#/components/responses/RailTransport"
          }
        }
      }
    },
    "/v1/receipts/{receipt_id}": {
      "get": {
        "summary": "Fetch a receipt",
        "security": [
          {
            "BearerServiceToken": []
          },
          {
            "MutualTLS": []
          }
        ],
        "parameters": [
          {
            "name": "receipt_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "receipt JSON",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReceiptMoneyV1"
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND"
          }
        }
      }
    },
    "/v1/receipts": {
      "get": {
        "summary": "Query receipts",
        "security": [
          {
            "BearerServiceToken": []
          },
          {
            "MutualTLS": []
          }
        ],
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "receipt list"
          }
        }
      }
    },
    "/v1/admin/agents/{agent_id}/suspend": {
      "post": {
        "summary": "Suspend an agent (admin kill switch)",
        "security": [
          {
            "BearerServiceToken": []
          },
          {
            "MutualTLS": []
          }
        ],
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "suspended"
          },
          "403": {
            "description": "forbidden"
          }
        }
      }
    },
    "/v1/receipts/verify": {
      "post": {
        "summary": "Verify an Ed25519-signed receipt-money-v1 payload (public example path)",
        "description": "Example verification against the published ABCP verifying key. Does not move money.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "valid or invalid boolean result"
          },
          "400": {
            "description": "malformed request"
          }
        }
      }
    },
    "/health": {
      "get": {
        "summary": "Liveness and deploy attestation for the public doctrine Worker",
        "responses": {
          "200": {
            "description": "ok, version, deploy_id, git_sha, last_promote"
          }
        }
      }
    }
  }
}
