{
  "openapi": "3.1.0",
  "info": {
    "title": "felipe-agents public-web utilities",
    "version": "1.0.0",
    "description": "Small, bounded public-web utilities for AI agents: normalized extraction, metadata checks, freshness checks, source-backed research packs, and API sanity reports. Paid routes use x402 v2 exact settlement on Base mainnet USDC or X Layer USDT0.",
    "contact": {
      "email": "huasi420@proton.me"
    }
  },
  "servers": [
    {
      "url": "https://felipeandrade.xyz",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Agent market and request intake",
    "url": "https://felipeandrade.xyz/agent-market"
  },
  "x-payment-rails": [
    {
      "protocol": "x402",
      "version": 2,
      "scheme": "exact",
      "network": "eip155:8453",
      "chain": "Base",
      "asset": "USDC",
      "assetAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "payTo": "0xb6e024d5e436d0a5698653ff3be8ddbf901e5649"
    },
    {
      "protocol": "x402",
      "version": 2,
      "scheme": "exact",
      "network": "eip155:196",
      "chain": "X Layer",
      "asset": "USDT0",
      "assetAddress": "0x779ded0c9e1022225f8e0630b35a9b54be713736",
      "assetVersion": "1",
      "payTo": "0xb6e024d5e436d0a5698653ff3be8ddbf901e5649"
    }
  ],
  "x-a2a": {
    "endpoint": "https://felipeandrade.xyz/api/agent",
    "protocolVersion": "0.3.0",
    "operations": ["message/send", "tasks/get", "tasks/cancel"],
    "serviceId": "scrape-json"
  },
  "tags": [
    {
      "name": "Agent utilities",
      "description": "Machine-facing public-web tasks."
    }
  ],
    "paths": {
    "/api/agent/scrape-json": {
      "post": {
        "tags": ["Agent utilities"],
        "summary": "Fetch a public URL as normalized evidence",
        "description": "Fetch one public HTML, JSON, XML, CSV, or text URL and return normalized text, links, tables, a timestamp, and a SHA-256 content hash.",
        "operationId": "scrapeJson",
        "security": [{"x402Payment": []}],
        "x-payment-info": {
          "protocols": ["x402"],
          "scheme": "exact",
          "asset": "USDC",
          "network": "eip155:8453",
          "price": {"mode": "fixed", "currency": "USD", "amount": "0.005"}
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/ScrapeRequest"},
              "example": {"input": {"url": "https://example.com"}}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Normalized public-page evidence",
            "content": {
              "application/json": {
                "schema": {"$ref": "#/components/schemas/ScrapeResponse"}
              }
            }
          },
          "402": {"$ref": "#/components/responses/PaymentRequired"},
          "503": {"$ref": "#/components/responses/ServiceUnavailable"}
        }
      }
    },
    "/api/agent/freshness-check": {
      "post": {
        "tags": ["Agent utilities"],
        "summary": "Check whether a public page changed",
        "description": "Fetch one public URL and compare its current SHA-256 text fingerprint with an optional supplied baseline.",
        "operationId": "freshnessCheck",
        "security": [{"x402Payment": []}],
        "x-payment-info": {
          "protocols": ["x402"],
          "scheme": "exact",
          "asset": "USDC",
          "network": "eip155:8453",
          "price": {"mode": "fixed", "currency": "USD", "amount": "0.001"}
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/FreshnessRequest"},
              "example": {"input": {"url": "https://example.com"}}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Freshness result",
            "content": {
              "application/json": {
                "schema": {"$ref": "#/components/schemas/FreshnessResponse"}
              }
            }
          },
          "402": {"$ref": "#/components/responses/PaymentRequired"},
          "503": {"$ref": "#/components/responses/ServiceUnavailable"}
        }
      }
    },
    "/api/agent/research-brief": {
      "post": {
        "tags": ["Agent utilities"],
        "summary": "Assemble a bounded source-backed research pack",
        "description": "Answer one bounded question from one to three public URLs with excerpts, timestamps, fingerprints, and visible evidence gaps.",
        "operationId": "researchBrief",
        "security": [{"x402Payment": []}],
        "x-payment-info": {
          "protocols": ["x402"],
          "scheme": "exact",
          "asset": "USDC",
          "network": "eip155:8453",
          "price": {"mode": "fixed", "currency": "USD", "amount": "0.05"}
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/ResearchRequest"},
              "example": {"input": {"question": "Compare these sources", "urls": ["https://example.com"]}}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Source-backed research pack",
            "content": {
              "application/json": {
                "schema": {"$ref": "#/components/schemas/ResearchResponse"}
              }
            }
          },
          "402": {"$ref": "#/components/responses/PaymentRequired"},
          "503": {"$ref": "#/components/responses/ServiceUnavailable"}
        }
      }
    },
    "/api/agent/api-sanity": {
      "get": {
        "tags": ["Agent utilities"],
        "summary": "Probe two public API endpoints over a GET query",
        "description": "Paid query form of the two-endpoint sanity report. Pass url1 and url2 as public HTTP endpoint URLs.",
        "operationId": "apiSanityGet",
        "security": [{"x402Payment": []}],
        "x-payment-info": {
          "protocols": ["x402"],
          "scheme": "exact",
          "asset": "USDC",
          "network": "eip155:8453",
          "price": {"mode": "fixed", "currency": "USD", "amount": "1"}
        },
        "parameters": [
          {"name": "url1", "in": "query", "required": true, "schema": {"type": "string", "format": "uri"}},
          {"name": "url2", "in": "query", "required": true, "schema": {"type": "string", "format": "uri"}}
        ],
        "responses": {
          "200": {
            "description": "Two-endpoint API sanity report",
            "content": {
              "application/json": {
                "schema": {"$ref": "#/components/schemas/ApiSanityResponse"}
              }
            }
          },
          "402": {"$ref": "#/components/responses/PaymentRequired"},
          "503": {"$ref": "#/components/responses/ServiceUnavailable"}
        }
      },
      "post": {
        "tags": ["Agent utilities"],
        "summary": "Probe two public API endpoints",
        "description": "GET exactly two public HTTP endpoints and return status codes, approximate latency, JSON sanity, and anomaly notes.",
        "operationId": "apiSanity",
        "security": [{"x402Payment": []}],
        "x-payment-info": {
          "protocols": ["x402"],
          "scheme": "exact",
          "asset": "USDC",
          "network": "eip155:8453",
          "price": {"mode": "fixed", "currency": "USD", "amount": "1"}
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/ApiSanityRequest"},
              "example": {"input": {"urls": ["https://example.com/health", "https://example.com/config"]}}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Two-endpoint API sanity report",
            "content": {
              "application/json": {
                "schema": {"$ref": "#/components/schemas/ApiSanityResponse"}
              }
            }
          },
          "402": {"$ref": "#/components/responses/PaymentRequired"},
          "503": {"$ref": "#/components/responses/ServiceUnavailable"}
        }
      }
    },
    "/api/agent/web-metadata": {
      "get": {
        "tags": ["Agent utilities"],
        "summary": "Read a public page's standard and Open Graph metadata over a GET query",
        "description": "Paid query form of the metadata check. Pass one public HTTP URL as url.",
        "operationId": "webMetadataGet",
        "security": [{"x402Payment": []}],
        "x-payment-info": {
          "protocols": ["x402"],
          "scheme": "exact",
          "asset": "USDC",
          "network": "eip155:8453",
          "price": {"mode": "fixed", "currency": "USD", "amount": "0.02"}
        },
        "parameters": [
          {"name": "url", "in": "query", "required": true, "schema": {"type": "string", "format": "uri"}}
        ],
        "responses": {
          "200": {
            "description": "Public-page metadata",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WebMetadataResponse"}}}
          },
          "402": {"$ref": "#/components/responses/PaymentRequired"},
          "503": {"$ref": "#/components/responses/ServiceUnavailable"}
        }
      },
      "post": {
        "tags": ["Agent utilities"],
        "summary": "Read a public page's standard and Open Graph metadata",
        "description": "Fetch one public HTML page and return its title, description, canonical URL, Open Graph fields, and check timestamp.",
        "operationId": "webMetadata",
        "security": [{"x402Payment": []}],
        "x-payment-info": {
          "protocols": ["x402"],
          "scheme": "exact",
          "asset": "USDC",
          "network": "eip155:8453",
          "price": {"mode": "fixed", "currency": "USD", "amount": "0.02"}
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/WebMetadataRequest"},
              "example": {"input": {"url": "https://example.com"}}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Public-page metadata",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WebMetadataResponse"}}}
          },
          "402": {"$ref": "#/components/responses/PaymentRequired"},
          "503": {"$ref": "#/components/responses/ServiceUnavailable"}
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "x402Payment": {
        "type": "apiKey",
        "in": "header",
        "name": "PAYMENT-SIGNATURE",
        "description": "x402 v2 payment signature for the exact USDC requirement returned in Payment-Required."
      }
    },
    "responses": {
      "PaymentRequired": {
        "description": "A valid x402 payment is required before the task runs.",
        "headers": {
          "Payment-Required": {
            "description": "Base mainnet USDC x402 v2 payment requirements, encoded as defined by x402.",
            "schema": {"type": "string"}
          }
        },
        "content": {
          "application/json": {
            "schema": {"type": "object", "additionalProperties": true}
          }
        }
      },
      "ServiceUnavailable": {
        "description": "The paid route is staged or temporarily unavailable; no charge is made.",
        "content": {
          "application/json": {
            "schema": {"$ref": "#/components/schemas/ErrorResponse"}
          }
        }
      }
    },
    "schemas": {
      "UrlInput": {
        "type": "object",
        "required": ["url"],
        "additionalProperties": false,
        "properties": {
          "url": {"type": "string", "format": "uri", "description": "One public HTTP or HTTPS URL."}
        }
      },
      "ScrapeRequest": {
        "type": "object",
        "required": ["input"],
        "additionalProperties": false,
        "properties": {
          "input": {"$ref": "#/components/schemas/UrlInput"}
        }
      },
      "FreshnessRequest": {
        "type": "object",
        "required": ["input"],
        "additionalProperties": false,
        "properties": {
          "input": {
            "type": "object",
            "required": ["url"],
            "additionalProperties": false,
            "properties": {
              "url": {"type": "string", "format": "uri", "description": "One public HTTP or HTTPS URL."},
              "previousFingerprint": {"type": "string", "description": "Optional prior sha256 fingerprint."}
            }
          }
        }
      },
      "ResearchRequest": {
        "type": "object",
        "required": ["input"],
        "additionalProperties": false,
        "properties": {
          "input": {
            "type": "object",
            "required": ["question", "urls"],
            "additionalProperties": false,
            "properties": {
              "question": {"type": "string", "minLength": 1},
              "urls": {
                "type": "array",
                "minItems": 1,
                "maxItems": 3,
                "items": {"type": "string", "format": "uri"}
              }
            }
          }
        }
      },
      "ApiSanityRequest": {
        "type": "object",
        "required": ["input"],
        "additionalProperties": false,
        "properties": {
          "input": {
            "type": "object",
            "required": ["urls"],
            "additionalProperties": false,
            "properties": {
              "urls": {
                "type": "array",
                "minItems": 2,
                "maxItems": 2,
                "items": {"type": "string", "format": "uri"}
              }
            }
          }
        }
      },
      "WebMetadataRequest": {
        "type": "object",
        "required": ["input"],
        "additionalProperties": false,
        "properties": {
          "input": {"$ref": "#/components/schemas/UrlInput"}
        }
      },
      "ScrapeResponse": {
        "type": "object",
        "description": "The response includes normalized public-page evidence, links, tables, a fetch timestamp, and a SHA-256 content hash.",
        "additionalProperties": true,
        "properties": {
          "service_id": {"type": "string", "const": "scrape-json"},
          "status": {"type": "string"},
          "source_url": {"type": "string", "format": "uri"},
          "content_hash": {"type": "string"},
          "fetched_at": {"type": "string", "format": "date-time"}
        }
      },
      "FreshnessResponse": {
        "type": "object",
        "description": "The response includes changed/no-change status, the current fingerprint, a compact diff when available, and a check timestamp.",
        "additionalProperties": true,
        "properties": {
          "service_id": {"type": "string", "const": "freshness-check"},
          "changed": {"type": ["boolean", "null"], "description": "Null when no previousFingerprint baseline is supplied."},
          "fingerprint": {"type": "string", "pattern": "^sha256:[a-f0-9]{64}$"},
          "checked_at": {"type": "string", "format": "date-time"}
        }
      },
      "ResearchResponse": {
        "type": "object",
        "description": "The response includes bounded synthesis, source records, excerpts or claims, timestamps, hashes, and visible gaps.",
        "additionalProperties": true,
        "properties": {
          "service_id": {"type": "string", "const": "research-brief"},
          "question": {"type": "string"},
          "sources": {"type": "array", "items": {"type": "object", "additionalProperties": true}},
          "gaps": {"type": "array", "items": {"type": "string"}}
        }
      },
      "ApiSanityResponse": {
        "type": "object",
        "description": "The response includes one record per endpoint with status, latency, content type, JSON sanity, and anomaly notes.",
        "additionalProperties": true,
        "properties": {
          "service_id": {"type": "string", "const": "api-sanity"},
          "status": {"type": "string"},
          "endpoints": {"type": "array", "minItems": 2, "maxItems": 2, "items": {"type": "object", "additionalProperties": true}},
          "checked_at": {"type": "string", "format": "date-time"}
        }
      },
      "WebMetadataResponse": {
        "type": "object",
        "description": "The response includes standard page metadata, canonical URL, Open Graph preview fields, and a check timestamp.",
        "additionalProperties": true,
        "properties": {
          "service_id": {"type": "string", "const": "web-metadata"},
          "status": {"type": "string", "const": "complete"},
          "source_url": {"type": "string", "format": "uri"},
          "title": {"type": ["string", "null"]},
          "description": {"type": ["string", "null"]},
          "canonical_url": {"type": ["string", "null"]},
          "open_graph": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "title": {"type": ["string", "null"]},
              "description": {"type": ["string", "null"]},
              "image": {"type": ["string", "null"]},
              "type": {"type": ["string", "null"]}
            }
          },
          "checked_at": {"type": "string", "format": "date-time"}
        }
      },
      "ErrorResponse": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "error": {"type": "string"},
          "message": {"type": "string"},
          "charged": {"type": "boolean", "const": false}
        }
      }
    }
  }
}
