{
  "openapi": "3.1.0",
  "info": {
    "title": "Trooth Public API",
    "version": "1.1.0",
    "summary": "The read-only public surface of the Trooth Network.",
    "description": "Everything here answers a question about a software or AI company from published\nevidence, and needs no credential. It is the surface a person, an integrator or an\nauthorized agent may build on.\n\nWHAT IS DELIBERATELY ABSENT. Authentication flows are not documented: they are\nbrowser redirects in a login sequence, not an API. Unauthenticated endpoints that\nsend mail or start work are rate limited and undocumented on purpose. Every\nsession-authenticated endpoint is absent because publishing an internal route map\nhelps an attacker and promises an API that is not offered.\n\nEVIDENCE VOCABULARY. Responses distinguish witnessed, verified, declared, inferred,\nunknown, unavailable, stale and conflicting. Unknown is an answer, never a blank\nfilled in, and stale is never the same as wrong.\n\nA 404 from these endpoints usually means the network holds no record, which is an\nanswer rather than a failure.\n\nGenerated from app/api by scripts/gen-openapi.mjs. check:openapi fails the build\nwhen this document and the source disagree.",
    "contact": {
      "name": "Trooth developer support",
      "email": "developers@trooth.co",
      "url": "https://trooth.co/developers"
    },
    "license": {
      "name": "Terms of Service",
      "url": "https://trooth.co/terms"
    }
  },
  "servers": [
    {
      "url": "https://trooth.co",
      "description": "Production"
    }
  ],
  "x-counts": {
    "paths": 8,
    "operations": 8
  },
  "paths": {
    "/api/mobile/directory/search": {
      "get": {
        "summary": "Search the Trooth Network",
        "description": "Full-text search over published company listings. Returns the same companies the public directory shows. Prefer cursor pagination: pass the returned next_cursor back as cursor. Offset pagination still works and is kept for clients that already ship with it, but it counts rows rather than naming a position, so a directory that grows between two requests can serve the same company twice and skip another without erroring. A cursor that cannot be read returns 400 rather than an empty page. Cached at the edge for 60 seconds with a 300 second stale-while-revalidate window.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Search terms. Matched against company name and description.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "industry",
            "in": "query",
            "required": false,
            "description": "Restrict to one industry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page. Clamped to 100; anything unreadable falls back to 25.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque page marker. Use next_cursor from the previous response. Preferred over offset.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Zero-based offset. Use next_offset from the previous response. Superseded by cursor.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "operationId": "get_api_mobile_directory_search",
        "security": [],
        "responses": {
          "200": {
            "description": "Success"
          },
          "404": {
            "description": "No such record. Not an error; the network does not hold it."
          }
        }
      }
    },
    "/api/mobile/directory/featured": {
      "get": {
        "summary": "Companies with a witnessed standing",
        "description": "The network's front page: published companies, those with a witnessed standing first. Cached at the edge for 120 seconds.",
        "operationId": "get_api_mobile_directory_featured",
        "security": [],
        "responses": {
          "200": {
            "description": "Success"
          },
          "404": {
            "description": "No such record. Not an error; the network does not hold it."
          }
        }
      }
    },
    "/api/mobile/directory/vendor/{slug}": {
      "get": {
        "summary": "One company record",
        "description": "A published company profile, and its live standing where the company has been witnessed. A slug of the form d--example.com resolves a witnessed company that has not yet published a rich profile. Cached at the edge for 120 seconds.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Company slug, or d--<domain>.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "get_api_mobile_directory_vendor_slug_",
        "security": [],
        "responses": {
          "200": {
            "description": "Success"
          },
          "404": {
            "description": "No such record. Not an error; the network does not hold it."
          }
        }
      }
    },
    "/api/public-mesh/{handle}": {
      "get": {
        "summary": "A company's public evidence rollup",
        "description": "The buyer-facing projection of a company's evidence: standing, framework rollups and provider status. Individual control rows, owners and internal notes are never returned here. Responds 404 when the company has no public scorecard, which is a privacy-preserving answer rather than an error.",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "description": "Company handle.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "get_api_public_mesh_handle_",
        "security": [],
        "responses": {
          "200": {
            "description": "Success"
          },
          "404": {
            "description": "No such record. Not an error; the network does not hold it."
          }
        }
      }
    },
    "/api/compare": {
      "get": {
        "summary": "Compare companies side by side",
        "description": "Verdict-only comparison across up to a handful of companies. Control rows are stripped, so a company's internal posture is never exposed through the comparison. Rate limited.",
        "parameters": [
          {
            "name": "handles",
            "in": "query",
            "required": true,
            "description": "Comma-separated company handles.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "get_api_compare",
        "security": [],
        "responses": {
          "200": {
            "description": "Success"
          },
          "404": {
            "description": "No such record. Not an error; the network does not hold it."
          },
          "429": {
            "description": "Rate limited. Retry after a short pause."
          }
        }
      }
    },
    "/api/network/suggest": {
      "get": {
        "summary": "Typeahead over published companies",
        "description": "Name-to-company suggestions for a search box, over the same published listings the directory shows. Cached at the edge for 60 seconds.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Partial company name.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "get_api_network_suggest",
        "security": [],
        "responses": {
          "200": {
            "description": "Success"
          },
          "404": {
            "description": "No such record. Not an error; the network does not hold it."
          }
        }
      }
    },
    "/api/legal/{slug}": {
      "get": {
        "summary": "A published legal document",
        "description": "The full text of one of the twenty published Trooth legal documents, with its title, effective date and body. The slug must be one of the published set; anything else responds 404. Cached at the edge for one hour with a one day stale-while-revalidate window.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Document slug, for example privacy, terms, subprocessors.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "get_api_legal_slug_",
        "security": [],
        "responses": {
          "200": {
            "description": "Success"
          },
          "404": {
            "description": "No such record. Not an error; the network does not hold it."
          }
        }
      }
    },
    "/api/version": {
      "get": {
        "summary": "The deployment currently serving",
        "description": "The build stamp of the running deployment. Never cached. Useful for confirming which release answered a request.",
        "operationId": "get_api_version",
        "security": [],
        "responses": {
          "200": {
            "description": "Success"
          },
          "404": {
            "description": "No such record. Not an error; the network does not hold it."
          }
        }
      }
    }
  }
}
