{
  "openapi": "3.1.0",
  "info": {
    "title": "The Clean Opinion — compliance readiness tools",
    "version": "1.0.0",
    "summary": "Planning estimates for SOC 2, SOX 404 and post-incident readiness, computed from the answers you supply.",
    "description": "These tools give planning estimates from the answers supplied. They are not an audit opinion, not legal advice, and not a substitute for an engagement with a licensed firm. Audits and attestations are performed by Alpha Secure LLP, a licensed CPA firm. Every weight, threshold and interval is practitioner judgement published at https://thecleanopinion.com/how-scoring-works/, not a figure set by the AICPA, the SEC, the PCAOB or NIST.\n\nAttribution: The Clean Opinion (thecleanopinion.com). If you relay one of these results, cite the publication and link the tool page in `source.tool`. That is the whole ask — there is no key to request and no signup.\n\nEvery endpoint that can be reached with a GET can be reached with a GET, deliberately: a browsing assistant can construct and fetch a URL, and most cannot POST a JSON body. The two endpoints that grade a pasted document accept POST, and one of them accepts nothing else.\n\nNo authentication. No API key. Rate limited to 60 requests a minute per address with a burst of 20; over that the service returns 429 with a Retry-After, never a 503.",
    "contact": {
      "name": "The Clean Opinion",
      "url": "https://thecleanopinion.com/tools/api/",
      "email": "hello@thecleanopinion.com"
    },
    "license": {
      "name": "Free to use with attribution",
      "url": "https://thecleanopinion.com/disclosure/"
    }
  },
  "security": [],
  "servers": [
    {
      "url": "https://thecleanopinion.com",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Using the tools from an agent",
    "url": "https://thecleanopinion.com/tools/api/"
  },
  "tags": [
    {
      "name": "soc2",
      "description": "Readiness tools for SOC 2."
    },
    {
      "name": "sox",
      "description": "Readiness tools for SOX."
    },
    {
      "name": "cyber",
      "description": "Readiness tools for Cyber."
    },
    {
      "name": "trust",
      "description": "Readiness tools for Trust."
    }
  ],
  "paths": {
    "/api/tools/security-questionnaire-panic-checker": {
      "get": {
        "operationId": "get_security_questionnaire_panic_checker",
        "summary": "What is a security questionnaire actually asking for?",
        "description": "Most vendor security questionnaires cover the same eight areas in different words. This checker sorts each line you paste into one of those areas by keyword, shows how the questions are distributed, lists the evidence a reviewer will want for each area, and flags the answers that are dangerous to guess at.\n\nGET answers from the context parameters alone. POST adds the questionnaire itself.\n\nWhat a URL cannot carry: The questionnaire itself — Capped at 200,000 characters, and a real one runs to tens or hundreds of kilobytes — far past what a URL can carry. A link pre-fills everything else; the visitor still pastes.\n\nLimits on the answer:\n- It sorts the questionnaire; it does not read it. Each line is filed under whichever of eight control areas its keywords match most, by fixed patterns and no language model. A line containing a trigger word is counted whether it is a question, a section header, a cover page or a cell from an answer column — the distribution is a rough shape, not a count of questions.\n- It reads the questionnaire, never your controls. The evidence list and the likely gaps are fixed text per control area: every company pasting an access-control question receives the same access-control gap. Nothing here is a finding about the company that sent the request.\n- Urgency scores the situation described in the answers supplied, not the control environment. If nothing in the paste matched a control area, a high score is capped at medium rather than raising an alarm built on text the checker could not read.\n- There is no category for risk assessment, personnel security, training, governance or physical security. Questions on those subjects appear in the unmatched list rather than under a control area.",
        "tags": [
          "soc2"
        ],
        "parameters": [
          {
            "name": "deadline",
            "in": "query",
            "required": false,
            "description": "Customer deadline. YYYY-MM-DD. Omit if none was given.",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "deal",
            "in": "query",
            "required": false,
            "description": "A live deal depends on it",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no"
              ]
            }
          },
          {
            "name": "soc2",
            "in": "query",
            "required": false,
            "description": "SOC 2 status today",
            "schema": {
              "type": "string",
              "enum": [
                "none",
                "in-progress",
                "type1",
                "type2"
              ]
            }
          },
          {
            "name": "asker",
            "in": "query",
            "required": false,
            "description": "Who is asking",
            "schema": {
              "type": "string",
              "enum": [
                "prospect",
                "customer",
                "insurer",
                "investor",
                "other"
              ]
            }
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "description": "Headcount",
            "schema": {
              "type": "string",
              "enum": [
                "1-10",
                "11-50",
                "51-200",
                "201-1000",
                "1000+"
              ]
            }
          },
          {
            "name": "asOf",
            "in": "query",
            "required": false,
            "description": "Compute the answer as of this date. YYYY-MM-DD, interpreted at midnight UTC. Omit for today. Pinning it makes the answer reproducible and cacheable; without it the same call returns different dates tomorrow.",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The computed answer, with the method, the limits, and the link to hand a person.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "404": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "post_security_questionnaire_panic_checker",
        "summary": "What is a security questionnaire actually asking for?",
        "description": "Most vendor security questionnaires cover the same eight areas in different words. This checker sorts each line you paste into one of those areas by keyword, shows how the questions are distributed, lists the evidence a reviewer will want for each area, and flags the answers that are dangerous to guess at.\n\nGET answers from the context parameters alone. POST adds the questionnaire itself.\n\nWhat a URL cannot carry: The questionnaire itself — Capped at 200,000 characters, and a real one runs to tens or hundreds of kilobytes — far past what a URL can carry. A link pre-fills everything else; the visitor still pastes.\n\nLimits on the answer:\n- It sorts the questionnaire; it does not read it. Each line is filed under whichever of eight control areas its keywords match most, by fixed patterns and no language model. A line containing a trigger word is counted whether it is a question, a section header, a cover page or a cell from an answer column — the distribution is a rough shape, not a count of questions.\n- It reads the questionnaire, never your controls. The evidence list and the likely gaps are fixed text per control area: every company pasting an access-control question receives the same access-control gap. Nothing here is a finding about the company that sent the request.\n- Urgency scores the situation described in the answers supplied, not the control environment. If nothing in the paste matched a control area, a high score is capped at medium rather than raising an alarm built on text the checker could not read.\n- There is no category for risk assessment, personnel security, training, governance or physical security. Questions on those subjects appear in the unmatched list rather than under a control area.",
        "tags": [
          "soc2"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "deadline": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "Customer deadline. YYYY-MM-DD. Omit if none was given."
                  },
                  "deal": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no"
                    ],
                    "description": "A live deal depends on it"
                  },
                  "soc2": {
                    "type": "string",
                    "enum": [
                      "none",
                      "in-progress",
                      "type1",
                      "type2"
                    ],
                    "description": "SOC 2 status today"
                  },
                  "asker": {
                    "type": "string",
                    "enum": [
                      "prospect",
                      "customer",
                      "insurer",
                      "investor",
                      "other"
                    ],
                    "description": "Who is asking"
                  },
                  "size": {
                    "type": "string",
                    "enum": [
                      "1-10",
                      "11-50",
                      "51-200",
                      "201-1000",
                      "1000+"
                    ],
                    "description": "Headcount"
                  },
                  "asOf": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "YYYY-MM-DD, interpreted at midnight UTC. Omit for today. Pinning it makes the answer reproducible and cacheable; without it the same call returns different dates tomorrow."
                  },
                  "text": {
                    "type": "string",
                    "description": "The questionnaire, pasted. Capped at 200,000 characters, which is the same cap the tool page enforces. A URL cannot carry a document of that size, so a GET answers from the context parameters alone — it returns the situation read, with a caveat saying nothing was sorted. POST this field to have the questions categorised."
                  }
                },
                "required": [],
                "additionalProperties": false
              },
              "examples": {
                "example1": {
                  "summary": "A prospect sent a questionnaire tied to a live deal, due in two weeks, with no SOC 2 report in hand.",
                  "value": {
                    "deadline": "2026-09-24",
                    "deal": "yes",
                    "soc2": "none",
                    "asker": "prospect",
                    "size": "11-50"
                  }
                },
                "example2": {
                  "summary": "An existing customer's annual re-review, no deadline pressure, Type 2 already held.",
                  "value": {
                    "deal": "no",
                    "soc2": "type2",
                    "asker": "customer",
                    "size": "51-200"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The computed answer, with the method, the limits, and the link to hand a person.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "404": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/tools/soc-2-timeline-calculator": {
      "get": {
        "operationId": "get_soc_2_timeline_calculator",
        "summary": "How long does a SOC 2 audit take?",
        "description": "There is no single answer — it depends almost entirely on how much is already in place. This calculator turns nine answers about your controls into three dated ranges: when a Type 1 could be ready, when a Type 1 report could be in hand, and when a Type 2 could be, then compares each against your customer's deadline.\n\nLimits on the answer:\n- These are planning estimates from the answers supplied, not an auditor's schedule. No auditor has seen this company, and an engagement letter will set real dates that supersede every range here.\n- Not one interval in the model is published by the AICPA. The remediation weeks, the parallelism factor, the fieldwork and report lags and the range spread are all practitioner judgement, published at https://thecleanopinion.com/how-scoring-works/ so the arithmetic can be checked or argued with.\n- The three-to-six-month observation window is market convention, not a rule. No AICPA document prescribes a minimum Type 2 observation period, or states a typical one — a vendor page claiming a mandatory six months is stating a rule that does not exist.\n- The Type 2 range is two scoping decisions — how long a window, and how much is already in place — rather than an error bar. Splitting the difference between the ends produces a date that answers neither question.",
        "tags": [
          "soc2"
        ],
        "parameters": [
          {
            "name": "goal",
            "in": "query",
            "required": false,
            "description": "Which report is being asked for. Anything else is read as type1.",
            "schema": {
              "type": "string",
              "enum": [
                "type1",
                "type2"
              ]
            }
          },
          {
            "name": "deadline",
            "in": "query",
            "required": false,
            "description": "Customer or procurement deadline. YYYY-MM-DD. Omit for a timeline with no deadline risk assessment.",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "p",
            "in": "query",
            "required": false,
            "description": "Written, approved security policies",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "partial"
              ]
            }
          },
          {
            "name": "a",
            "in": "query",
            "required": false,
            "description": "Access reviews performed and evidenced",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "partial"
              ]
            }
          },
          {
            "name": "v",
            "in": "query",
            "required": false,
            "description": "Vendor reviews performed and evidenced",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "partial"
              ]
            }
          },
          {
            "name": "ir",
            "in": "query",
            "required": false,
            "description": "Incident response plan, tested",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "partial"
              ]
            }
          },
          {
            "name": "e",
            "in": "query",
            "required": false,
            "description": "Control evidence collected routinely",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "partial"
              ]
            }
          },
          {
            "name": "ks",
            "in": "query",
            "required": false,
            "description": "In-scope systems. Clamped to 1–200; a non-number is read as 5.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "owner",
            "in": "query",
            "required": false,
            "description": "A named owner for the work. 1 or 0.",
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "0"
              ]
            }
          },
          {
            "name": "asOf",
            "in": "query",
            "required": false,
            "description": "Compute the answer as of this date. YYYY-MM-DD, interpreted at midnight UTC. Omit for today. Pinning it makes the answer reproducible and cacheable; without it the same call returns different dates tomorrow.",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The computed answer, with the method, the limits, and the link to hand a person.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "404": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "post_soc_2_timeline_calculator",
        "summary": "How long does a SOC 2 audit take?",
        "description": "There is no single answer — it depends almost entirely on how much is already in place. This calculator turns nine answers about your controls into three dated ranges: when a Type 1 could be ready, when a Type 1 report could be in hand, and when a Type 2 could be, then compares each against your customer's deadline.\n\nLimits on the answer:\n- These are planning estimates from the answers supplied, not an auditor's schedule. No auditor has seen this company, and an engagement letter will set real dates that supersede every range here.\n- Not one interval in the model is published by the AICPA. The remediation weeks, the parallelism factor, the fieldwork and report lags and the range spread are all practitioner judgement, published at https://thecleanopinion.com/how-scoring-works/ so the arithmetic can be checked or argued with.\n- The three-to-six-month observation window is market convention, not a rule. No AICPA document prescribes a minimum Type 2 observation period, or states a typical one — a vendor page claiming a mandatory six months is stating a rule that does not exist.\n- The Type 2 range is two scoping decisions — how long a window, and how much is already in place — rather than an error bar. Splitting the difference between the ends produces a date that answers neither question.",
        "tags": [
          "soc2"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "goal": {
                    "type": "string",
                    "enum": [
                      "type1",
                      "type2"
                    ],
                    "description": "Which report is being asked for. Anything else is read as type1."
                  },
                  "deadline": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "Customer or procurement deadline. YYYY-MM-DD. Omit for a timeline with no deadline risk assessment."
                  },
                  "p": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "partial"
                    ],
                    "description": "Written, approved security policies"
                  },
                  "a": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "partial"
                    ],
                    "description": "Access reviews performed and evidenced"
                  },
                  "v": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "partial"
                    ],
                    "description": "Vendor reviews performed and evidenced"
                  },
                  "ir": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "partial"
                    ],
                    "description": "Incident response plan, tested"
                  },
                  "e": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "partial"
                    ],
                    "description": "Control evidence collected routinely"
                  },
                  "ks": {
                    "type": "integer",
                    "description": "In-scope systems. Clamped to 1–200; a non-number is read as 5."
                  },
                  "owner": {
                    "type": "string",
                    "enum": [
                      "1",
                      "0"
                    ],
                    "description": "A named owner for the work. 1 or 0."
                  },
                  "asOf": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "YYYY-MM-DD, interpreted at midnight UTC. Omit for today. Pinning it makes the answer reproducible and cacheable; without it the same call returns different dates tomorrow."
                  }
                },
                "required": [],
                "additionalProperties": false
              },
              "examples": {
                "example1": {
                  "summary": "A prospect asked for a Type 2 report by the end of March, and nothing is evidenced yet.",
                  "value": {
                    "goal": "type2",
                    "deadline": "2027-03-31",
                    "p": "partial",
                    "a": "no",
                    "v": "no",
                    "ir": "partial",
                    "e": "no",
                    "ks": 8,
                    "owner": "0"
                  }
                },
                "example2": {
                  "summary": "Controls are in place and owned; the question is only how soon a Type 1 can be in hand.",
                  "value": {
                    "goal": "type1",
                    "p": "yes",
                    "a": "yes",
                    "v": "yes",
                    "ir": "yes",
                    "e": "yes",
                    "ks": 5,
                    "owner": "1"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The computed answer, with the method, the limits, and the link to hand a person.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "404": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/tools/sox-404-deadline-calculator": {
      "get": {
        "operationId": "get_sox_404_deadline_calculator",
        "summary": "When does your first SOX 404 assessment actually apply?",
        "description": "Not on the date you went public. This calculator works out the first fiscal year-end that management's Section 404(a) assessment plausibly applies to, then lays out a working first-year calendar backwards from it. It produces a year-end to plan against, not a filing deadline, and it does not determine your filer status.\n\nLimits on the answer:\n- It produces a fiscal year-end to plan against, not a filing deadline. The date the 10-K is due is a separate calculation this tool does not make.\n- The single assumption to confirm first is transition relief. The result assumes a newly public company's first annual report generally carries no management 404(a) report, which keys off registration history rather than the IPO date — for a de-SPAC survivor or a company with prior reporting history the real date is a year earlier than the one returned, and nothing in the supplied answers lets the code detect it. Item 308 of Regulation S-K and securities counsel settle it.\n- Filer status is taken at face value and never verified against public float, revenue or reporting history. It is re-determined each year. 'Smaller reporting companies are exempt from 404(b)' is wrong as stated: the exemption attaches to non-accelerated filer status, and an SRC with a float between $250 million and $700 million and revenue at or above $100 million is an accelerated filer to whom 404(b) applies.\n- The 404(b) note carries a caveat about SEC Release 33-11419, proposed in May 2026 and still a proposal rather than a final rule. The calculator applies the rules in force, and the note was last reviewed in August 2026.",
        "tags": [
          "sox"
        ],
        "parameters": [
          {
            "name": "public",
            "in": "query",
            "required": true,
            "description": "Public-company date. YYYY-MM-DD. IPO pricing, de-SPAC close, or effectiveness. Not before 1990-01-01.",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "fye",
            "in": "query",
            "required": true,
            "description": "Fiscal year-end. MM-DD, e.g. 12-31 or 01-31. MM/DD and MMDD are also read.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filer",
            "in": "query",
            "required": false,
            "description": "Filer status. Defaults to not-sure, which returns a caveated answer rather than a guess.",
            "schema": {
              "type": "string",
              "enum": [
                "large-accelerated",
                "accelerated",
                "non-accelerated",
                "smaller-reporting",
                "emerging-growth",
                "not-sure"
              ]
            }
          },
          {
            "name": "rev",
            "in": "query",
            "required": false,
            "description": "Annual revenue. Whole US dollars, e.g. 250000000. The form field takes millions; this parameter does not.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "float",
            "in": "query",
            "required": false,
            "description": "Public float. Whole US dollars, e.g. 700000000. Drives the 404(b) answer, so an unsure value is better omitted.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "tenk",
            "in": "query",
            "required": false,
            "description": "First 10-K date, if known. YYYY-MM-DD.",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "owner",
            "in": "query",
            "required": true,
            "description": "A named ITGC owner. 1 or 0.",
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "0"
              ]
            }
          },
          {
            "name": "sys",
            "in": "query",
            "required": false,
            "description": "Financially relevant systems. Comma-separated. Unrecognised entries are dropped.",
            "schema": {
              "type": "string",
              "description": "Comma-separated. Accepted members: erp, payroll, billing, data-warehouse, crm, other. Unrecognised entries are dropped rather than guessed at."
            }
          },
          {
            "name": "access",
            "in": "query",
            "required": true,
            "description": "Access-review evidence retained",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "partial"
              ]
            }
          },
          {
            "name": "change",
            "in": "query",
            "required": true,
            "description": "Change-management evidence retained",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "partial"
              ]
            }
          },
          {
            "name": "asOf",
            "in": "query",
            "required": false,
            "description": "Compute the answer as of this date. YYYY-MM-DD, interpreted at midnight UTC. Omit for today. Pinning it makes the answer reproducible and cacheable; without it the same call returns different dates tomorrow.",
            "schema": {
              "type": "string",
              "format": "date",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The computed answer, with the method, the limits, and the link to hand a person.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "404": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "post_sox_404_deadline_calculator",
        "summary": "When does your first SOX 404 assessment actually apply?",
        "description": "Not on the date you went public. This calculator works out the first fiscal year-end that management's Section 404(a) assessment plausibly applies to, then lays out a working first-year calendar backwards from it. It produces a year-end to plan against, not a filing deadline, and it does not determine your filer status.\n\nLimits on the answer:\n- It produces a fiscal year-end to plan against, not a filing deadline. The date the 10-K is due is a separate calculation this tool does not make.\n- The single assumption to confirm first is transition relief. The result assumes a newly public company's first annual report generally carries no management 404(a) report, which keys off registration history rather than the IPO date — for a de-SPAC survivor or a company with prior reporting history the real date is a year earlier than the one returned, and nothing in the supplied answers lets the code detect it. Item 308 of Regulation S-K and securities counsel settle it.\n- Filer status is taken at face value and never verified against public float, revenue or reporting history. It is re-determined each year. 'Smaller reporting companies are exempt from 404(b)' is wrong as stated: the exemption attaches to non-accelerated filer status, and an SRC with a float between $250 million and $700 million and revenue at or above $100 million is an accelerated filer to whom 404(b) applies.\n- The 404(b) note carries a caveat about SEC Release 33-11419, proposed in May 2026 and still a proposal rather than a final rule. The calculator applies the rules in force, and the note was last reviewed in August 2026.",
        "tags": [
          "sox"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "public": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "Public-company date. YYYY-MM-DD. IPO pricing, de-SPAC close, or effectiveness. Not before 1990-01-01."
                  },
                  "fye": {
                    "type": "string",
                    "description": "Fiscal year-end. MM-DD, e.g. 12-31 or 01-31. MM/DD and MMDD are also read."
                  },
                  "filer": {
                    "type": "string",
                    "enum": [
                      "large-accelerated",
                      "accelerated",
                      "non-accelerated",
                      "smaller-reporting",
                      "emerging-growth",
                      "not-sure"
                    ],
                    "description": "Filer status. Defaults to not-sure, which returns a caveated answer rather than a guess."
                  },
                  "rev": {
                    "type": "integer",
                    "description": "Annual revenue. Whole US dollars, e.g. 250000000. The form field takes millions; this parameter does not."
                  },
                  "float": {
                    "type": "integer",
                    "description": "Public float. Whole US dollars, e.g. 700000000. Drives the 404(b) answer, so an unsure value is better omitted."
                  },
                  "tenk": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "First 10-K date, if known. YYYY-MM-DD."
                  },
                  "owner": {
                    "type": "string",
                    "enum": [
                      "1",
                      "0"
                    ],
                    "description": "A named ITGC owner. 1 or 0."
                  },
                  "sys": {
                    "type": "string",
                    "description": "Financially relevant systems. Comma-separated. Unrecognised entries are dropped."
                  },
                  "access": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "partial"
                    ],
                    "description": "Access-review evidence retained"
                  },
                  "change": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "partial"
                    ],
                    "description": "Change-management evidence retained"
                  },
                  "asOf": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                    "description": "YYYY-MM-DD, interpreted at midnight UTC. Omit for today. Pinning it makes the answer reproducible and cacheable; without it the same call returns different dates tomorrow."
                  }
                },
                "required": [],
                "additionalProperties": false
              },
              "examples": {
                "example1": {
                  "summary": "A company that listed in March 2026 with a December year-end, no named ITGC owner, and no evidence retained yet.",
                  "value": {
                    "public": "2026-03-15",
                    "fye": "12-31",
                    "filer": "non-accelerated",
                    "owner": "0",
                    "sys": "erp,payroll",
                    "access": "no",
                    "change": "no"
                  }
                },
                "example2": {
                  "summary": "An accelerated filer with a $700M float and a January year-end, checking whether 404(b) applies.",
                  "value": {
                    "public": "2025-06-30",
                    "fye": "01-31",
                    "filer": "accelerated",
                    "rev": 250000000,
                    "float": 700000000,
                    "owner": "1",
                    "sys": "erp,billing,data-warehouse",
                    "access": "partial",
                    "change": "yes"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The computed answer, with the method, the limits, and the link to hand a person.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "404": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/tools/breach-aftermath-control-checklist": {
      "get": {
        "operationId": "get_breach_aftermath_control_checklist",
        "summary": "What will auditors, insurers and your board ask for after a breach?",
        "description": "The second wave of a breach is questions. This checklist takes eight answers about the incident and selects, from a fixed library, the controls to review, the evidence to gather, and the questions each party — customers, your cyber insurer, the board, your auditor, lenders — tends to ask, alongside the artifact that answers each one.\n\nLimits on the answer:\n- The score measures scrutiny implied, not severity. Each party already asking questions is worth fourteen points out of a hundred before any fact about the incident is weighed, so a minor incident several parties have noticed outscores a serious one nobody has asked about yet.\n- 'Critical' on an item means a party already asking will raise it. It is not a judgement about how badly the company is exposed.\n- The items are selected from a fixed library by the eight answers supplied. Nothing here is a finding about this incident, and the list is not a legal or regulatory notification checklist — breach notification obligations turn on jurisdiction, contract and counsel, none of which this tool knows.\n- It does not replace counsel or an incident-response provider, and it assumes the incident itself is already being handled.",
        "tags": [
          "cyber"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "What kind of incident. ransomware and vendor-incident each imply the matching question below unless it is answered otherwise.",
            "schema": {
              "type": "string",
              "enum": [
                "ransomware",
                "credential-compromise",
                "vendor-incident",
                "data-exposure",
                "insider",
                "other"
              ]
            }
          },
          {
            "name": "data",
            "in": "query",
            "required": false,
            "description": "Customer or personal data involved",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "unknown"
              ]
            }
          },
          {
            "name": "fin",
            "in": "query",
            "required": false,
            "description": "Financial systems touched. ERP, billing, payroll, banking, or the identity provider in front of them.",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "unknown"
              ]
            }
          },
          {
            "name": "vendor",
            "in": "query",
            "required": false,
            "description": "A third-party vendor involved",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "unknown"
              ]
            }
          },
          {
            "name": "ransom",
            "in": "query",
            "required": false,
            "description": "Ransomware involved",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "unknown"
              ]
            }
          },
          {
            "name": "disclosed",
            "in": "query",
            "required": false,
            "description": "A public disclosure already made",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "unknown"
              ]
            }
          },
          {
            "name": "asking",
            "in": "query",
            "required": false,
            "description": "Who is already asking questions. Comma-separated. Blank is a real answer: nobody has asked yet.",
            "schema": {
              "type": "string",
              "description": "Comma-separated. Accepted members: customers, insurer, board, auditor, lenders-investors. Unrecognised entries are dropped rather than guessed at."
            }
          },
          {
            "name": "remediation",
            "in": "query",
            "required": false,
            "description": "Documented remediation evidence",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no",
                "partial",
                "unknown"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The computed answer, with the method, the limits, and the link to hand a person.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "404": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "post_breach_aftermath_control_checklist",
        "summary": "What will auditors, insurers and your board ask for after a breach?",
        "description": "The second wave of a breach is questions. This checklist takes eight answers about the incident and selects, from a fixed library, the controls to review, the evidence to gather, and the questions each party — customers, your cyber insurer, the board, your auditor, lenders — tends to ask, alongside the artifact that answers each one.\n\nLimits on the answer:\n- The score measures scrutiny implied, not severity. Each party already asking questions is worth fourteen points out of a hundred before any fact about the incident is weighed, so a minor incident several parties have noticed outscores a serious one nobody has asked about yet.\n- 'Critical' on an item means a party already asking will raise it. It is not a judgement about how badly the company is exposed.\n- The items are selected from a fixed library by the eight answers supplied. Nothing here is a finding about this incident, and the list is not a legal or regulatory notification checklist — breach notification obligations turn on jurisdiction, contract and counsel, none of which this tool knows.\n- It does not replace counsel or an incident-response provider, and it assumes the incident itself is already being handled.",
        "tags": [
          "cyber"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "ransomware",
                      "credential-compromise",
                      "vendor-incident",
                      "data-exposure",
                      "insider",
                      "other"
                    ],
                    "description": "What kind of incident. ransomware and vendor-incident each imply the matching question below unless it is answered otherwise."
                  },
                  "data": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "unknown"
                    ],
                    "description": "Customer or personal data involved"
                  },
                  "fin": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "unknown"
                    ],
                    "description": "Financial systems touched. ERP, billing, payroll, banking, or the identity provider in front of them."
                  },
                  "vendor": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "unknown"
                    ],
                    "description": "A third-party vendor involved"
                  },
                  "ransom": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "unknown"
                    ],
                    "description": "Ransomware involved"
                  },
                  "disclosed": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "unknown"
                    ],
                    "description": "A public disclosure already made"
                  },
                  "asking": {
                    "type": "string",
                    "description": "Who is already asking questions. Comma-separated. Blank is a real answer: nobody has asked yet."
                  },
                  "remediation": {
                    "type": "string",
                    "enum": [
                      "yes",
                      "no",
                      "partial",
                      "unknown"
                    ],
                    "description": "Documented remediation evidence"
                  }
                },
                "required": [],
                "additionalProperties": false
              },
              "examples": {
                "example1": {
                  "summary": "Credentials were compromised, customer data was involved, and the auditor and insurer are both asking.",
                  "value": {
                    "type": "credential-compromise",
                    "data": "yes",
                    "fin": "yes",
                    "vendor": "no",
                    "ransom": "no",
                    "disclosed": "no",
                    "remediation": "partial",
                    "asking": "insurer,auditor"
                  }
                },
                "example2": {
                  "summary": "The bare minimum: three questions answered, nobody asking yet, everything else still unknown.",
                  "value": {
                    "type": "vendor-incident",
                    "data": "unknown",
                    "fin": "no"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The computed answer, with the method, the limits, and the link to hand a person.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "404": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/tools/trust-page-grader": {
      "post": {
        "operationId": "post_trust_page_grader",
        "summary": "What should a trust page include?",
        "description": "Ten things, in roughly the order enterprise reviewers look for them: an audit report, a trust page or security overview, a privacy policy, a subprocessor list, a way to request evidence, a security contact, a status page, a vulnerability disclosure path, an incident response process, and data retention and deletion.\n\nPOST only. There is no GET, because a GET could only be answered by fetching the page for you, which this service will not do.\n\nWhat a URL cannot carry: The pasted page — Capped at 200,000 characters, and a real one runs to tens or hundreds of kilobytes — far past what a URL can carry. A link pre-fills everything else; the visitor still pastes.\n\nLimits on the answer:\n- It grades a page, not a company. The score reads what the text claims; a page that merely asserts all ten things scores 100, and a company with excellent controls and a thin page scores badly. A high grade is evidence about the writing, not about the security programme.\n- The address is never fetched — not by this tool and not by anything behind it. Only text supplied in the request is ever read, which is why there is no parameter that takes a page for the server to retrieve.\n- Detection is keyword and pattern matching over the text. Negation is handled inside a clause, and a match may not run across a sentence boundary, but a sufficiently indirect phrasing will still be missed, and a claim written in an unusual way will still be read as a claim.\n- A flagged claim means the wording would not survive a reviewer asking for the certificate, not that the statement is false.",
        "tags": [
          "trust"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "The address of the page being graded. Display only — it is never fetched, by this tool or by anything behind it. Capped at 2048 characters; a non-http(s) scheme is dropped."
                  },
                  "enterprise": {
                    "type": "string",
                    "enum": [
                      "1",
                      "0"
                    ],
                    "description": "Selling to enterprise buyers. 1 or 0."
                  },
                  "asking": {
                    "type": "string",
                    "enum": [
                      "1",
                      "0"
                    ],
                    "description": "Customers ask for security documentation. 1 or 0."
                  },
                  "pageText": {
                    "type": "string",
                    "description": "The trust or security page, pasted as text. Required. Capped at 200,000 characters, which is the same cap the tool page enforces. There is no parameter that takes a URL for this service to fetch."
                  }
                },
                "required": [
                  "pageText"
                ],
                "additionalProperties": false
              },
              "examples": {
                "example1": {
                  "summary": "A company moving upmarket whose buyers have started asking for documentation.",
                  "value": {
                    "url": "https://example.com/security",
                    "enterprise": "1",
                    "asking": "1",
                    "pageText": "<the full text of the page you are grading, which you fetch yourself>"
                  }
                },
                "example2": {
                  "summary": "A self-check before going upmarket, with no documentation requests yet.",
                  "value": {
                    "url": "https://example.com/trust",
                    "enterprise": "0",
                    "asking": "0",
                    "pageText": "<the full text of the page you are grading, which you fetch yourself>"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The computed answer, with the method, the limits, and the link to hand a person.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "404": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request could not be answered as asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/tools/openapi.json": {
      "get": {
        "operationId": "get_openapi",
        "summary": "This document.",
        "responses": {
          "200": {
            "description": "The OpenAPI 3.1 description of this API.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/tools/health": {
      "get": {
        "operationId": "get_health",
        "summary": "Liveness, and the commit the service was built from.",
        "description": "`buildSha` is the git commit of the site this service was built alongside. It is checked against the deployed site after every deploy, so a sidecar left behind by a failed deploy is visible rather than silently answering with last week's rubric.",
        "responses": {
          "200": {
            "description": "The service is up.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "service": {
                      "type": "string"
                    },
                    "buildSha": {
                      "type": "string"
                    },
                    "tools": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Envelope": {
        "type": "object",
        "required": [
          "tool",
          "name",
          "result",
          "explain",
          "caveat",
          "nextSteps",
          "source",
          "citation",
          "humanUrl",
          "meta"
        ],
        "properties": {
          "tool": {
            "type": "string",
            "description": "The tool slug, matching the last path segment."
          },
          "name": {
            "type": "string"
          },
          "asOf": {
            "type": "string",
            "format": "date",
            "description": "The date the answer was computed for. Present only on endpoints whose answer moves with the clock; its absence means the result does not depend on when it was asked."
          },
          "result": {
            "type": "object",
            "additionalProperties": true,
            "description": "The computed answer. Its shape differs per tool and is documented in prose on that tool's page and in the `explain` field below. It never contains the site's internal lead-scoring fields."
          },
          "explain": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "How this tool works, in plain English, one paragraph per step. The same text the tool's own page publishes, verbatim."
          },
          "caveat": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What this answer is not. The standing limits of the tool first, then anything this particular run has to add about itself — an assumption it made, an input it could not read, a paste it had to truncate. Relay these with the result; they are the difference between a relayed answer being incomplete and being wrong."
          },
          "nextSteps": {
            "type": "array",
            "description": "Ordered things to do, from the tool's own output. Never invented here.",
            "items": {
              "type": "object",
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "detail": {
                  "type": "string"
                },
                "targetDate": {
                  "type": "string",
                  "format": "date",
                  "description": "Present where the step is dated."
                }
              }
            }
          },
          "source": {
            "type": "object",
            "description": "Who to credit, and where the method is published so it can be checked or argued with.",
            "properties": {
              "name": {
                "type": "string"
              },
              "url": {
                "type": "string",
                "format": "uri"
              },
              "tool": {
                "type": "string",
                "format": "uri"
              },
              "attribution": {
                "type": "string"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              },
              "professionalWorkBy": {
                "type": "object",
                "description": "The licensed CPA firm that performs the professional work. It does not own this publication.",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          },
          "citation": {
            "type": "array",
            "description": "Primary sources behind anything in `explain` that comes from a regulator or standard-setter. Often empty: most of these tools rest on practitioner judgement, and say so.",
            "items": {
              "type": "object",
              "required": [
                "title",
                "url"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "humanUrl": {
            "type": "string",
            "format": "uri",
            "description": "The same answers as a link to the tool page, carrying utm_source=agent. Hand this to the person you are helping: it opens the page with their answers already filled in. For the two tools that take a pasted document, the link carries everything except the paste, and the visitor still pastes."
          },
          "meta": {
            "type": "object",
            "properties": {
              "unrecognizedParams": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Parameters that were sent and ignored. Named rather than silently dropped, so a caller working from a stale contract can tell."
              },
              "disclaimer": {
                "type": "string"
              },
              "documentation": {
                "type": "string",
                "format": "uri"
              },
              "manifest": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message",
          "documentation"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "A stable machine-readable code."
          },
          "message": {
            "type": "string",
            "description": "What went wrong and what would have worked, in a sentence a model can act on."
          },
          "documentation": {
            "type": "string",
            "format": "uri"
          },
          "manifest": {
            "type": "string",
            "format": "uri"
          },
          "missing": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Required parameters the request did not carry."
          },
          "parameters": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "The full parameter list for this endpoint."
          }
        }
      }
    },
    "responses": {
      "RateLimited": {
        "description": "Too many requests from this address. Wait for `Retry-After` seconds and try again; the service is not broken.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds to wait."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
