{
  "openapi": "3.1.0",
  "info": {
    "title": "Is Zack a Dad? API",
    "version": "1.0.0",
    "summary": "One question, answered with considerably more API than it needs.",
    "description": "Public, read-only, unauthenticated. Every `/api/*` endpoint sends `Access-Control-Allow-Origin: *`, answers CORS preflights, and is rate-limited to 120 requests a minute per IP (exceed it and you get a `429` with a JSON body and `Retry-After`). Every response also carries an `X-Is-Zack-A-Dad` header, because why not.",
    "contact": {
      "name": "Is Zack a Dad?",
      "url": "https://iszacka.dad/api"
    }
  },
  "servers": [
    {
      "url": "https://iszacka.dad"
    }
  ],
  "externalDocs": {
    "description": "Human-readable documentation",
    "url": "https://iszacka.dad/api"
  },
  "tags": [
    {
      "name": "Status",
      "description": "The answer, in various levels of verbosity."
    },
    {
      "name": "Updates",
      "description": "History and the update stream."
    },
    {
      "name": "Feeds",
      "description": "Syndication formats for people who still use feed readers (correctly)."
    },
    {
      "name": "Widgets",
      "description": "Badges and embeds."
    },
    {
      "name": "Machines",
      "description": "MCP, OpenAPI and the various .txt files robots like."
    }
  ],
  "paths": {
    "/api/status": {
      "get": {
        "tags": [
          "Status"
        ],
        "summary": "The answer, as JSON",
        "operationId": "getStatus",
        "responses": {
          "200": {
            "description": "The current answer.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Status"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/status.json": {
      "get": {
        "tags": [
          "Status"
        ],
        "summary": "The answer, as JSON (with a file extension, for the traditionalists)",
        "description": "Identical to `/api/status`.",
        "operationId": "getStatusJson",
        "responses": {
          "200": {
            "description": "The current answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Status"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/status.txt": {
      "get": {
        "tags": [
          "Status"
        ],
        "summary": "The answer, as one line of plain text",
        "description": "Exactly one of `no`, `not yet` or `yes`, followed by a newline.",
        "operationId": "getStatusText",
        "responses": {
          "200": {
            "description": "The answer.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "no\n",
                    "not yet\n",
                    "yes\n"
                  ]
                },
                "example": "no\n"
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/history": {
      "get": {
        "tags": [
          "Updates"
        ],
        "summary": "Every status the site has ever had, oldest first",
        "operationId": "getHistory",
        "responses": {
          "200": {
            "description": "Status history.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/History"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/updates": {
      "get": {
        "tags": [
          "Updates"
        ],
        "summary": "The update stream, newest first",
        "operationId": "listUpdates",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "How many updates to return.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          {
            "name": "before",
            "in": "query",
            "description": "Only updates with an id lower than this (pagination cursor).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of updates.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdatePage"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/dad": {
      "get": {
        "tags": [
          "Status"
        ],
        "summary": "Request one dad",
        "description": "Returns `425 Too Early` (RFC 8470) until Zack is a dad, with a `Retry-After` computed from the due date when one is known (hourly once overdue, every minute during labour). Once Zack is a dad: `201 Created` with `Location: /`. POST works identically, for the semantically minded.",
        "operationId": "getDad",
        "responses": {
          "201": {
            "description": "Zack is a dad.",
            "headers": {
              "Location": {
                "description": "Always `/`.",
                "schema": {
                  "type": "string",
                  "const": "/"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DadCreated"
                }
              }
            }
          },
          "425": {
            "description": "Too early. Zack is not a dad yet.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DadTooEarly"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "tags": [
          "Status"
        ],
        "summary": "Request one dad (POST)",
        "description": "Same as GET. No request body is needed or read.",
        "operationId": "postDad",
        "responses": {
          "201": {
            "description": "Zack is a dad.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DadCreated"
                }
              }
            }
          },
          "425": {
            "description": "Too early.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DadTooEarly"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/stream": {
      "get": {
        "tags": [
          "Status"
        ],
        "summary": "Live updates as Server-Sent Events",
        "description": "A long-lived `text/event-stream`. Each event carries a JSON live message: `hello` on connect, then `state`, `update`, `viewers`, `vibes`, `checks` and `reload` as they happen. Try `curl -N`.",
        "operationId": "streamLive",
        "responses": {
          "200": {
            "description": "An endless stream of suspense.",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/feed.xml": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "summary": "RSS 2.0 feed",
        "description": "The latest 50 updates. Cached for 60 seconds; send If-None-Match with the ETag to get a 304.",
        "operationId": "getRss",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "The feed.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/rss+xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          }
        }
      }
    },
    "/rss.xml": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "summary": "RSS 2.0 feed (alias)",
        "description": "The same RSS feed as `/feed.xml`. Cached for 60 seconds; send If-None-Match with the ETag to get a 304.",
        "operationId": "getRssAlias",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "The feed.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/rss+xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          }
        }
      }
    },
    "/atom.xml": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "summary": "Atom 1.0 feed",
        "description": "The latest 50 updates. Cached for 60 seconds; send If-None-Match with the ETag to get a 304.",
        "operationId": "getAtom",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "The feed.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/atom+xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          }
        }
      }
    },
    "/feed.json": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "summary": "JSON Feed 1.1",
        "description": "The latest 50 updates. Cached for 60 seconds; send If-None-Match with the ETag to get a 304.",
        "operationId": "getJsonFeed",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "The feed.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/feed+json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          }
        }
      }
    },
    "/calendar.ics": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "summary": "iCalendar subscription",
        "description": "The due date as an all-day event, plus \"It's happening\" and \"Zack became a dad\" events at the moment they happen. Asks calendar apps to refresh hourly. Cached for 60 seconds; send If-None-Match with the ETag to get a 304.",
        "operationId": "getCalendar",
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "The feed.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "text/calendar": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          }
        }
      }
    },
    "/badge.svg": {
      "get": {
        "tags": [
          "Widgets"
        ],
        "summary": "A shields.io-style status badge",
        "operationId": "getBadge",
        "parameters": [
          {
            "name": "style",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "flat",
                "flat-square",
                "for-the-badge"
              ],
              "default": "flat"
            }
          },
          {
            "name": "label",
            "in": "query",
            "description": "Left-hand text (default \"is zack a dad?\"). Trimmed to 40 characters; empty hides it.",
            "schema": {
              "type": "string",
              "maxLength": 40
            }
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "The badge.",
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          }
        }
      }
    },
    "/embed": {
      "get": {
        "tags": [
          "Widgets"
        ],
        "summary": "A tiny widget page for iframes",
        "description": "Frameable from anywhere (`frame-ancestors *`). Refreshes itself every 60 seconds.",
        "operationId": "getEmbed",
        "parameters": [
          {
            "name": "theme",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "auto",
                "light",
                "dark"
              ],
              "default": "auto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "HTML.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/embed.js": {
      "get": {
        "tags": [
          "Widgets"
        ],
        "summary": "Script-tag embed",
        "description": "Renders a widget in a shadow DOM next to the script tag, polling `/api/status` every 60 seconds. Configure with `data-theme` (auto, light, dark), `data-size` (small, medium, large), `data-target` (CSS selector to render into) and `data-link` (\"false\" to drop the link).",
        "operationId": "getEmbedScript",
        "responses": {
          "200": {
            "description": "JavaScript.",
            "content": {
              "text/javascript": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "tags": [
          "Machines"
        ],
        "summary": "Model Context Protocol (Streamable HTTP)",
        "description": "Stateless MCP server with JSON responses. Supported protocol versions: 2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26. Modern (2026-07-28) clients send per-request `_meta` plus `MCP-Protocol-Version`, `Mcp-Method` and `Mcp-Name` headers; legacy clients call `initialize` first. Tools: `is_zack_a_dad`, `get_due_date_info`, `get_recent_updates`, `get_dad_forecast`.",
        "operationId": "mcp",
        "parameters": [
          {
            "name": "MCP-Protocol-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "enum": [
                "2026-07-28",
                "2025-11-25",
                "2025-06-18",
                "2025-03-26"
              ]
            }
          },
          {
            "name": "Mcp-Method",
            "in": "header",
            "description": "Required for 2026-07-28 requests; must equal the body `method`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Mcp-Name",
            "in": "header",
            "description": "Required for 2026-07-28 `tools/call`; must equal `params.name`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcMessage"
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/call",
                "params": {
                  "name": "is_zack_a_dad",
                  "arguments": {},
                  "_meta": {
                    "io.modelcontextprotocol/protocolVersion": "2026-07-28",
                    "io.modelcontextprotocol/clientCapabilities": {}
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A JSON-RPC response (or, for 2025-03-26 batches, an array of them).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "202": {
            "description": "Notification accepted. No body."
          },
          "400": {
            "description": "Malformed request, header mismatch or unsupported protocol version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "403": {
            "description": "Invalid Origin header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown method (2026-07-28 requests).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "406": {
            "description": "Accept excludes application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "413": {
            "description": "Body over 64 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "415": {
            "description": "Content-Type is not application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Machines"
        ],
        "summary": "Not supported",
        "description": "Stateless server: there is no SSE stream to GET.",
        "operationId": "mcpGet",
        "responses": {
          "405": {
            "description": "Method Not Allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": [
          "Machines"
        ],
        "summary": "This document",
        "operationId": "getOpenApi",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "tags": [
          "Machines"
        ],
        "summary": "llms.txt",
        "operationId": "getLlmsTxt",
        "responses": {
          "200": {
            "description": "Markdown, per llmstxt.org.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/humans.txt": {
      "get": {
        "tags": [
          "Machines"
        ],
        "summary": "humans.txt",
        "operationId": "getHumansTxt",
        "responses": {
          "200": {
            "description": "Credits.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/robots.txt": {
      "get": {
        "tags": [
          "Machines"
        ],
        "summary": "robots.txt",
        "operationId": "getRobotsTxt",
        "responses": {
          "200": {
            "description": "Crawler rules.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "tags": [
          "Machines"
        ],
        "summary": "XML sitemap",
        "operationId": "getSitemap",
        "responses": {
          "200": {
            "description": "Every public page.",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/security.txt": {
      "get": {
        "tags": [
          "Machines"
        ],
        "summary": "security.txt (RFC 9116)",
        "operationId": "getSecurityTxt",
        "responses": {
          "200": {
            "description": "How to report vulnerabilities (in the website).",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "StatusValue": {
        "type": "string",
        "enum": [
          "no",
          "soon",
          "yes"
        ],
        "description": "`soon` means labour has started."
      },
      "Status": {
        "type": "object",
        "required": [
          "isZackADad",
          "status",
          "answer",
          "sentence",
          "statusChangedAt",
          "dueDate",
          "daysUntilDue",
          "checks",
          "links"
        ],
        "properties": {
          "isZackADad": {
            "type": "boolean"
          },
          "status": {
            "$ref": "#/components/schemas/StatusValue"
          },
          "answer": {
            "type": "string",
            "enum": [
              "NO",
              "NOT YET",
              "YES"
            ]
          },
          "sentence": {
            "type": "string"
          },
          "statusChangedAt": {
            "type": "string",
            "format": "date-time"
          },
          "dueDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "daysUntilDue": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Negative when overdue. Null without a due date."
          },
          "checks": {
            "type": "integer",
            "minimum": 0,
            "description": "How many times anyone has asked."
          },
          "links": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "format": "uri"
            }
          }
        },
        "example": {
          "isZackADad": false,
          "status": "no",
          "answer": "NO",
          "sentence": "Zack is not a dad. Yet.",
          "statusChangedAt": "2026-11-06T09:00:00.000Z",
          "dueDate": "2026-11-20",
          "daysUntilDue": 14,
          "checks": 4096,
          "links": {
            "self": "https://iszacka.dad/api/status",
            "html": "https://iszacka.dad/"
          }
        }
      },
      "History": {
        "type": "object",
        "required": [
          "current",
          "history"
        ],
        "properties": {
          "current": {
            "$ref": "#/components/schemas/StatusValue"
          },
          "history": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "status",
                "at"
              ],
              "properties": {
                "status": {
                  "$ref": "#/components/schemas/StatusValue"
                },
                "at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          }
        }
      },
      "Update": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "title",
          "body",
          "status",
          "createdAt",
          "url"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "kind": {
            "type": "string",
            "enum": [
              "status",
              "daily",
              "system"
            ]
          },
          "title": {
            "type": "string"
          },
          "body": {
            "type": "string",
            "description": "Plain text; may contain newlines."
          },
          "status": {
            "$ref": "#/components/schemas/StatusValue"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "UpdatePage": {
        "type": "object",
        "required": [
          "updates",
          "nextBefore",
          "next"
        ],
        "properties": {
          "updates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Update"
            }
          },
          "nextBefore": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Pass as `before` for the next page. Null on the last page."
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          }
        }
      },
      "DadTooEarly": {
        "type": "object",
        "required": [
          "error",
          "status",
          "isZackADad",
          "message",
          "dueDate",
          "retryAfterSeconds",
          "retryAt"
        ],
        "properties": {
          "error": {
            "const": "too_early"
          },
          "status": {
            "type": "string",
            "enum": [
              "no",
              "soon"
            ]
          },
          "isZackADad": {
            "const": false
          },
          "message": {
            "type": "string"
          },
          "dueDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "retryAfterSeconds": {
            "type": [
              "integer",
              "null"
            ]
          },
          "retryAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "DadCreated": {
        "type": "object",
        "required": [
          "status",
          "isZackADad",
          "message",
          "createdAt",
          "location"
        ],
        "properties": {
          "status": {
            "const": "yes"
          },
          "isZackADad": {
            "const": true
          },
          "message": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "location": {
            "const": "/"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "JsonRpcMessage": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer"
            ]
          },
          "method": {
            "type": "string"
          },
          "params": {
            "type": "object"
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer",
              "null"
            ]
          },
          "result": {
            "type": "object"
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              },
              "data": {}
            }
          }
        }
      }
    },
    "parameters": {
      "IfNoneMatch": {
        "name": "If-None-Match",
        "in": "header",
        "description": "An ETag from a previous response.",
        "schema": {
          "type": "string"
        }
      }
    },
    "headers": {
      "ETag": {
        "description": "Entity tag for conditional requests.",
        "schema": {
          "type": "string"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before asking again.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "NoStore": {
        "description": "Always `no-store`: the answer could change at any moment.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "NotModified": {
        "description": "Not modified since the ETag you sent."
      },
      "RateLimited": {
        "description": "Too many requests (over 120 a minute from one IP).",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
