{
  "openapi": "3.1.0",
  "info": {
    "title": "Sutrace public content API",
    "version": "0.1.0-preview",
    "summary": "Read-only access to Sutrace's public content surface — blog posts, use cases, alternatives, comparisons — as static markdown files at predictable URLs.",
    "description": "Sutrace is a B2B observability platform unifying industrial hardware, software infrastructure, web & APIs, and AI agents in one dashboard. The full ingest API (write workspace data) is in private preview; this OpenAPI describes the public read surface that crawlers and AI agents can consume today.\n\nEvery HTML page has a raw markdown twin at the same URL with `.md` appended. Prefer the markdown for ingestion — fewer tokens, no DOM parsing.",
    "contact": {
      "name": "Sutrace",
      "url": "https://sutrace.io",
      "email": "hello@sutrace.io"
    },
    "termsOfService": "https://sutrace.io/legal/terms",
    "license": {
      "name": "Proprietary",
      "url": "https://sutrace.io/legal/terms"
    }
  },
  "servers": [
    { "url": "https://sutrace.io", "description": "Marketing + content" },
    { "url": "https://app.sutrace.io", "description": "Customer dashboard (auth-gated)" },
    { "url": "https://admin.sutrace.io", "description": "Operator-only admin (allowlist + Firestore rules)" }
  ],
  "paths": {
    "/llms.txt": {
      "get": {
        "summary": "LLM-friendly site overview",
        "operationId": "getLlmsIndex",
        "responses": {
          "200": {
            "description": "Plain text index pointing AI agents at the canonical pages.",
            "content": { "text/plain": { "schema": { "type": "string" } } }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "summary": "Comprehensive LLM map of every public page",
        "operationId": "getLlmsFull",
        "responses": {
          "200": { "description": "Plain text index with HTML and .md twin URLs.", "content": { "text/plain": { "schema": { "type": "string" } } } }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "summary": "XML sitemap",
        "operationId": "getSitemap",
        "responses": { "200": { "description": "XML sitemap.", "content": { "application/xml": { "schema": { "type": "string" } } } } }
      }
    },
    "/blog/feed.xml": {
      "get": {
        "summary": "RSS feed of journal posts",
        "operationId": "getBlogFeed",
        "responses": { "200": { "description": "RSS 2.0 feed.", "content": { "application/rss+xml": { "schema": { "type": "string" } } } } }
      }
    },
    "/blog/{slug}": {
      "get": {
        "summary": "Get a journal post (HTML)",
        "operationId": "getBlogPost",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "HTML page with JSON-LD.", "content": { "text/html": { "schema": { "type": "string" } } } } }
      }
    },
    "/blog/{slug}.md": {
      "get": {
        "summary": "Get a journal post (raw markdown)",
        "operationId": "getBlogPostMarkdown",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Raw markdown source.", "content": { "text/markdown": { "schema": { "type": "string" } } } } }
      }
    },
    "/use-cases/{slug}.md": {
      "get": {
        "summary": "Get a use-case page (raw markdown)",
        "operationId": "getUseCaseMarkdown",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Raw markdown source.", "content": { "text/markdown": { "schema": { "type": "string" } } } } }
      }
    },
    "/alternatives/{slug}.md": {
      "get": {
        "summary": "Get an alternative one-pager (raw markdown)",
        "operationId": "getAlternativeMarkdown",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Raw markdown source.", "content": { "text/markdown": { "schema": { "type": "string" } } } } }
      }
    },
    "/compare/{slug}.md": {
      "get": {
        "summary": "Get a head-to-head comparison (raw markdown)",
        "operationId": "getCompareMarkdown",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Raw markdown source.", "content": { "text/markdown": { "schema": { "type": "string" } } } } }
      }
    },
    "/.well-known/api-catalog": {
      "get": {
        "summary": "RFC 9727 API catalog",
        "operationId": "getApiCatalog",
        "responses": { "200": { "description": "Linkset.", "content": { "application/linkset+json": { "schema": { "type": "object" } } } } }
      }
    },
    "/api/v1/observe/device": {
      "post": {
        "summary": "Observe a device — agent-payable, per-device-day metered (preview)",
        "description": "Submit observability data for one device. Returns 402 Payment Required with x402 challenge if the agent's wallet has no quota; pays automatically via the SDK. $0.50 USD per device per day.",
        "operationId": "observeDevice",
        "tags": ["agent-payable"],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceTelemetry" } } }
        },
        "responses": {
          "200": { "description": "Accepted. Receipt returned.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Receipt" } } } },
          "402": { "description": "Payment Required. x402 challenge returned.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/X402Challenge" } } } }
        },
        "security": [{ "bearer": ["observe:device"] }, { "x402": [] }]
      }
    },
    "/api/v1/observe/trace": {
      "post": {
        "summary": "Submit OpenTelemetry spans — agent-payable, per-1k-span metered (preview)",
        "operationId": "observeTrace",
        "tags": ["agent-payable"],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OtelBatch" } } }
        },
        "responses": {
          "200": { "description": "Accepted. Receipt returned.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Receipt" } } } },
          "402": { "description": "Payment Required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/X402Challenge" } } } }
        },
        "security": [{ "bearer": ["observe:trace"] }, { "x402": [] }]
      }
    },
    "/api/v1/observe/llm_call": {
      "post": {
        "summary": "Observe an LLM call — agent-payable, per-call metered (preview)",
        "description": "Submit one observed LLM call (request, response, model, tokens, latency). Returns prompt-injection probability + cost analysis. $0.001 USD per call.",
        "operationId": "observeLlmCall",
        "tags": ["agent-payable"],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LlmCall" } } }
        },
        "responses": {
          "200": { "description": "Accepted. Receipt + analysis returned.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Receipt" } } } },
          "402": { "description": "Payment Required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/X402Challenge" } } } }
        },
        "security": [{ "bearer": ["observe:agent"] }, { "x402": [] }]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Workspace tokens minted by Firebase Auth (for human users) or via OAuth 2.0 client_credentials (for agents). Required for /app and /admin paths and the /api/v1/observe/* metered endpoints."
      },
      "x402": {
        "type": "http",
        "scheme": "x402",
        "description": "HTTP 402 Payment Required protocol. Agents settle metered SKUs via USDC on base-sepolia (preview) / base-mainnet (GA)."
      }
    },
    "schemas": {
      "DeviceTelemetry": {
        "type": "object",
        "required": ["device_id", "samples"],
        "properties": {
          "device_id": { "type": "string", "description": "Stable identifier of the observed device." },
          "samples": { "type": "array", "items": { "type": "object" }, "description": "Up to 100k samples per device per day." }
        }
      },
      "OtelBatch": {
        "type": "object",
        "required": ["resource_spans"],
        "properties": {
          "resource_spans": { "type": "array", "items": { "type": "object" }, "description": "OTLP resource spans payload." }
        }
      },
      "LlmCall": {
        "type": "object",
        "required": ["model", "prompt_hash"],
        "properties": {
          "model": { "type": "string" },
          "provider": { "type": "string", "description": "openai, anthropic, azure, bedrock, openrouter, etc." },
          "prompt_hash": { "type": "string", "description": "SHA-256 of the prompt — Sutrace defaults never see the raw prompt." },
          "prompt_tokens": { "type": "integer" },
          "completion_tokens": { "type": "integer" },
          "latency_ms": { "type": "number" },
          "cost_usd": { "type": "number" }
        }
      },
      "Receipt": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "amount": { "type": "string" },
          "currency": { "type": "string" },
          "asset": { "type": "string" },
          "tx": { "type": "string" },
          "signed_at": { "type": "string", "format": "date-time" }
        }
      },
      "X402Challenge": {
        "type": "object",
        "properties": {
          "amount": { "type": "string" },
          "currency": { "type": "string" },
          "asset": { "type": "string" },
          "settlement_network": { "type": "string" },
          "deadline": { "type": "string", "format": "date-time" },
          "nonce": { "type": "string" }
        }
      }
    }
  },
  "x-sutrace": {
    "publisher": "Sutrace",
    "status": "preview",
    "note": "Two surfaces: (1) public read-only content at sutrace.io (live, no auth); (2) three agent-payable observability SKUs at /api/v1/observe/* (private preview, x402 settlement on base-sepolia). The Sutrace ingest API for human-provisioned workspaces uses Firebase Auth from app.sutrace.io.",
    "contact": "hello@sutrace.io",
    "trust_center": "https://sutrace.io/legal/trust",
    "agent_billing_documentation": "https://sutrace.io/use-cases/agent-payable-observability"
  }
}
