{
  "openapi": "3.1.0",
  "info": {
    "title": "trump.fm API",
    "version": "0.3.0",
    "description": "Public, read-only API for the trump.fm archive of Donald J. Trump's posts on X (Twitter) from May 2009 until the account was suspended on January 8, 2021, and on Truth Social since February 14, 2022, including posts since deleted from the platforms. Not in the archive: his X posts after the account was restored, other accounts such as @POTUS, and what he said without posting it (speeches, interviews and rallies appear only as video he posted).\n\nEach post comes with what the archive adds to it: machine transcripts of its video and descriptions of its images (`transcripts`), the recovered text of what it reposted (`repostOf`, `repostSource`), a narration mp3 read by a synthesized voice (`audioUrl`), a machine-generated psychological analysis with fact checks (`/api/analysis/{postId}`), and receipts: contradictions between it and statements made at other times (`/api/receipts`). Each day with posts has a digest (`/api/digests`).\n\nPost text is his, except in reposts (`isRepost`, `repostSource`) and in early X retweets made by hand, which quote another account in quotation marks (`\"@handle: ...\"`). Transcripts, descriptions, analyses, digests and narration are machine output.\n\nNo authentication. CORS is open. Per IP: 100 requests a minute across /api, and 30 a minute for search and its counts. Past either, a 429 carries Retry-After.\n\nEvery page on the site also has a markdown view, the same content without the HTML: append `.md` to the page path (`/post/{id}.md`, `/date/{date}/analysis.md`, `/index.md`) or send `Accept: text/markdown`.\n\nPage URLs, for citing and linking:\n- Post: https://trump.fm/post/{id}\n- Post analysis: https://trump.fm/post/{id}/analysis\n- Day: https://trump.fm/date/{YYYY-MM-DD}\n- Day analysis: https://trump.fm/date/{YYYY-MM-DD}/analysis\n- Contradictions: https://trump.fm/contradictions\n- Narration: https://static.trump.fm/audio/{id}.mp3",
    "contact": {
      "email": "contact@trump.fm"
    },
    "license": {
      "name": "MIT",
      "identifier": "MIT"
    }
  },
  "security": [],
  "externalDocs": {
    "description": "Full documentation for agents",
    "url": "https://trump.fm/llms-full.txt"
  },
  "servers": [
    {
      "url": "https://trump.fm"
    }
  ],
  "tags": [
    {
      "name": "Posts",
      "description": "Retrieve and browse posts"
    },
    {
      "name": "Search",
      "description": "Full-text search across posts, transcripts, image descriptions and reposted text"
    },
    {
      "name": "Analysis",
      "description": "Machine-generated psychological analysis of individual posts, and daily digests"
    },
    {
      "name": "Receipts",
      "description": "Contradictions between statements made at different times"
    },
    {
      "name": "Stats",
      "description": "Aggregate statistics"
    },
    {
      "name": "Citations",
      "description": "Academic citation generation (JSON, RIS, BibTeX)"
    },
    {
      "name": "Sync",
      "description": "Operator sync from Truth Social (requires authorization)"
    }
  ],
  "paths": {
    "/api/posts": {
      "get": {
        "tags": [
          "Posts"
        ],
        "summary": "List posts",
        "description": "Posts newest first, paged by cursor. `from` starts the page at the end of a given day, and `direction=newer` walks forward from the cursor instead of back.",
        "operationId": "listPosts",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Page size. Values outside 1 to 100 are clamped."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "`meta.cursor` from the previous page."
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Start at the end of this day (YYYY-MM-DD) and page back from there. Ignored when `cursor` is given."
          },
          {
            "name": "direction",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "older",
                "newer"
              ],
              "default": "older"
            }
          },
          {
            "name": "platform",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "twitter",
                "truth"
              ],
              "default": "all"
            }
          },
          {
            "name": "includeDeleted",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            },
            "description": "Include posts that were later deleted. Pass \"false\" to exclude."
          }
        ],
        "responses": {
          "200": {
            "description": "Posts, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Post"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/CursorMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/posts/latest": {
      "get": {
        "tags": [
          "Posts"
        ],
        "summary": "Newest post the sync has seen",
        "description": "A cheap way to tell whether anything new has arrived: the id and time of the newest post, and when it was synced. `data` is null before the first sync.",
        "operationId": "getLatestSync",
        "responses": {
          "200": {
            "description": "Latest sync marker",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/LatestSync"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/posts/bulk": {
      "get": {
        "tags": [
          "Posts"
        ],
        "summary": "Get several posts by ID",
        "operationId": "getPostsBulk",
        "parameters": [
          {
            "name": "ids",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated post IDs, at most 50. IDs past the 50th are ignored, and unknown IDs are left out of the result."
          }
        ],
        "responses": {
          "200": {
            "description": "Matching posts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Post"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/posts/{id}": {
      "get": {
        "tags": [
          "Posts"
        ],
        "summary": "Get a single post",
        "operationId": "getPost",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Post ID: `ts_` and the Truth Social status id, or `x_` and the tweet id."
          }
        ],
        "responses": {
          "200": {
            "description": "The post",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Post"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/CursorMeta"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/posts/date/{date}": {
      "get": {
        "tags": [
          "Posts"
        ],
        "summary": "Get every post from one day",
        "operationId": "getPostsByDate",
        "parameters": [
          {
            "name": "date",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "A calendar day, YYYY-MM-DD, in UTC."
          }
        ],
        "responses": {
          "200": {
            "description": "The day's posts, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Post"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "cursor": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "hasMore": {
                          "type": "boolean"
                        },
                        "total": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/search": {
      "get": {
        "tags": [
          "Search"
        ],
        "summary": "Search posts",
        "description": "Full-text search over post text, the transcripts of posted video, descriptions of posted images (and any text in them), and the text of reposted posts. A hit that came from anything but the post's own words says so in `matchContext`.\n\nMatches words, not meaning: join synonyms, nicknames and spellings with OR in capitals (obamacare OR \"affordable care act\"), quote an exact phrase (\"witch hunt\"), end a word with * for its prefix (tariff*), and put - before a word to exclude it. Common words such as \"the\" are ignored outside quotes, and an exclusion needs a word to exclude from. No match means the words aren't in this archive, not that he never said them.\n\nPrefix a tag with `tag:` (`tag:grievance`) to list the posts an analysis tagged with it instead.",
        "operationId": "searchPosts",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            },
            "description": "Search terms, or `tag:{name}`. `OR` between alternatives, `\"exact phrase\"`, `prefix*`, `-excluded`."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Page size. Values outside 1 to 100 are clamped."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "`meta.cursor` from the previous page."
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "newest",
                "oldest"
              ],
              "default": "newest"
            },
            "description": "`oldest` lists first mentions first; its cursor then pages forward in time."
          },
          {
            "name": "platform",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "twitter",
                "truth"
              ],
              "default": "all"
            }
          },
          {
            "name": "startDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Only posts on or after this day (YYYY-MM-DD)."
          },
          {
            "name": "endDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Only posts on or before this day (YYYY-MM-DD)."
          }
        ],
        "responses": {
          "200": {
            "description": "Matching posts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Post"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/CursorMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/search/counts": {
      "get": {
        "tags": [
          "Search"
        ],
        "summary": "Count search matches over time",
        "description": "How many posts a word search matches, per year or month and platform, over the same match set as `/api/search`. A post counts once however often it repeats the words. Periods with no match are left out, newest last. `tag:` queries aren't counted.",
        "operationId": "countSearchMatches",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            },
            "description": "Search terms, with the syntax `/api/search` takes."
          },
          {
            "name": "by",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "year",
                "month"
              ],
              "default": "year"
            }
          },
          {
            "name": "platform",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "twitter",
                "truth"
              ],
              "default": "all"
            }
          },
          {
            "name": "startDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Only posts on or after this day (YYYY-MM-DD)."
          },
          {
            "name": "endDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Only posts on or before this day (YYYY-MM-DD)."
          }
        ],
        "responses": {
          "200": {
            "description": "Matching posts per period",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/MatchCount"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "total",
                        "by"
                      ],
                      "properties": {
                        "total": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "by": {
                          "type": "string",
                          "enum": [
                            "year",
                            "month"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/popular": {
      "get": {
        "tags": [
          "Posts"
        ],
        "summary": "Popular posts",
        "description": "Posts ranked by engagement (likes plus twice the reposts) within a rolling window, paged by offset.",
        "operationId": "getPopularPosts",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Page size. Values outside 1 to 100 are clamped."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "platform",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "twitter",
                "truth"
              ],
              "default": "all"
            }
          },
          {
            "name": "period",
            "in": "query",
            "description": "Rolling window reaching back to 00:00 UTC of the day 7, 30 or 365 days ago, or the whole archive.",
            "schema": {
              "type": "string",
              "enum": [
                "week",
                "month",
                "year",
                "all"
              ],
              "default": "month"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Popular posts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Post"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "offset": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "period": {
                          "type": "string",
                          "enum": [
                            "week",
                            "month",
                            "year",
                            "all"
                          ]
                        },
                        "hasMore": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/trending": {
      "get": {
        "tags": [
          "Posts"
        ],
        "summary": "Trending posts",
        "description": "Recently active posts ranked by engagement velocity.",
        "operationId": "getTrendingPosts",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Page size. Values outside 1 to 100 are clamped."
          },
          {
            "name": "platform",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "twitter",
                "truth"
              ],
              "default": "all"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Trending posts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Post"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "limit": {
                          "type": "integer"
                        },
                        "hasMore": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/stats": {
      "get": {
        "tags": [
          "Stats"
        ],
        "summary": "Archive statistics",
        "operationId": "getStats",
        "responses": {
          "200": {
            "description": "Archive counts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Stats"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/cite/{postId}": {
      "get": {
        "tags": [
          "Citations"
        ],
        "summary": "Generate citations for a post",
        "description": "APA, MLA and Chicago citations as JSON, or a RIS or BibTeX file for reference managers.",
        "operationId": "getCitation",
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Post ID: `ts_` and the Truth Social status id, or `x_` and the tweet id."
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "ris",
                "bibtex",
                "bib"
              ],
              "default": "json"
            },
            "description": "Output format. RIS and BibTeX come back as file downloads; anything else is JSON."
          }
        ],
        "responses": {
          "200": {
            "description": "Citations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "required": [
                        "postId",
                        "citations",
                        "downloadLinks"
                      ],
                      "properties": {
                        "postId": {
                          "type": "string"
                        },
                        "citations": {
                          "type": "object",
                          "properties": {
                            "apa": {
                              "type": "string"
                            },
                            "mla": {
                              "type": "string"
                            },
                            "chicago": {
                              "type": "string"
                            },
                            "bibtex": {
                              "type": "string"
                            },
                            "ris": {
                              "type": "string"
                            }
                          }
                        },
                        "downloadLinks": {
                          "type": "object",
                          "properties": {
                            "ris": {
                              "type": "string"
                            },
                            "bibtex": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              },
              "application/x-research-info-systems": {
                "schema": {
                  "type": "string"
                }
              },
              "application/x-bibtex": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/analysis/{postId}": {
      "get": {
        "tags": [
          "Analysis"
        ],
        "summary": "Get the analysis of a post",
        "description": "The full analysis record: summary and body, authorship, psychological profile, danger assessment, fact checks, tags, and the post's receipts. Machine-generated; see the about page for what that means and doesn't.",
        "operationId": "getPostAnalysis",
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Post ID: `ts_` and the Truth Social status id, or `x_` and the tweet id."
          }
        ],
        "responses": {
          "200": {
            "description": "The analysis",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Commentary"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/analysis/date/{date}": {
      "get": {
        "tags": [
          "Analysis"
        ],
        "summary": "Get a day's digest",
        "description": "The daily digest: the day's headline, summary and narrative across all its posts, with claim counts computed from the day's analyses.",
        "operationId": "getDailyDigest",
        "parameters": [
          {
            "name": "date",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "A calendar day, YYYY-MM-DD, in UTC."
          }
        ],
        "responses": {
          "200": {
            "description": "The digest",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DailyDigest"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/analyses/date/{date}": {
      "get": {
        "tags": [
          "Analysis"
        ],
        "summary": "Get every post analysis from one day",
        "operationId": "getAnalysesByDate",
        "parameters": [
          {
            "name": "date",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "A calendar day, YYYY-MM-DD, in UTC."
          }
        ],
        "responses": {
          "200": {
            "description": "The day's analyses, in post order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Commentary"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/analysis-stats": {
      "get": {
        "tags": [
          "Analysis"
        ],
        "summary": "Analysis statistics",
        "operationId": "getAnalysisStats",
        "responses": {
          "200": {
            "description": "Aggregate analysis counts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "totalCommentaries": {
                          "type": "integer"
                        },
                        "totalDigests": {
                          "type": "integer"
                        },
                        "dangerElevated": {
                          "type": "integer"
                        },
                        "dangerHigh": {
                          "type": "integer"
                        },
                        "dangerCritical": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/analysis-latest": {
      "get": {
        "tags": [
          "Analysis"
        ],
        "summary": "Most recent day with a digest",
        "operationId": "getLatestDigestDate",
        "responses": {
          "200": {
            "description": "The date, or null before any digest exists",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "oneOf": [
                        {
                          "type": "object",
                          "required": [
                            "date"
                          ],
                          "properties": {
                            "date": {
                              "type": "string",
                              "format": "date"
                            }
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/digests": {
      "get": {
        "tags": [
          "Analysis"
        ],
        "summary": "List days with a digest",
        "description": "Newest first, paged by cursor: pass `meta.cursor` back as `cursor` for the next page. Fetch a whole digest with `/api/analysis/date/{date}`.",
        "operationId": "listDigests",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 30
            },
            "description": "Page size. Values outside 1 to 100 are clamped."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Only days before this one."
          },
          {
            "name": "startDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Only days on or after this one."
          },
          {
            "name": "endDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Only days on or before this one."
          }
        ],
        "responses": {
          "200": {
            "description": "Digest summaries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DigestSummary"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/CursorMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/receipts": {
      "get": {
        "tags": [
          "Receipts"
        ],
        "summary": "Browse contradictions",
        "description": "Every contradiction the archive has found between two statements made at different times, filtered and sorted the way https://trump.fm/contradictions is. Each pair of posts appears once, as its most severe and most confident reading. By default only contradictions at or above 0.7 confidence are listed.",
        "operationId": "browseReceipts",
        "parameters": [
          {
            "name": "severity",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "reversal",
                "major",
                "moderate",
                "minor"
              ],
              "default": "all"
            }
          },
          {
            "name": "topic",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "A topic slug from `/api/receipts/topics`. Spaces become dashes and case is ignored."
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "severity",
                "recent",
                "days-apart"
              ],
              "default": "severity"
            }
          },
          {
            "name": "confidence",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "confident",
                "all"
              ],
              "default": "confident"
            },
            "description": "`all` includes the weak readings below 0.7."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Page size. Values outside 1 to 100 are clamped."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contradictions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ReceiptWithContext"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/OffsetMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/receipts/topics": {
      "get": {
        "tags": [
          "Receipts"
        ],
        "summary": "List contradiction topics",
        "description": "Every topic contradictions are filed under, busiest first, with counts by severity.",
        "operationId": "listReceiptTopics",
        "parameters": [
          {
            "name": "confidence",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "confident",
                "all"
              ],
              "default": "confident"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Topics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ReceiptTopic"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "confidence": {
                          "type": "string",
                          "enum": [
                            "confident",
                            "all"
                          ]
                        },
                        "total": {
                          "type": "integer"
                        },
                        "severityCounts": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/receipts/latest": {
      "get": {
        "tags": [
          "Receipts"
        ],
        "summary": "Most recently found contradictions",
        "operationId": "getLatestReceipts",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "description": "Page size. Values outside 1 to 100 are clamped."
          }
        ],
        "responses": {
          "200": {
            "description": "Contradictions, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ReceiptWithContext"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/CountMeta"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/receipts/topic/{topic}": {
      "get": {
        "tags": [
          "Receipts"
        ],
        "summary": "Contradictions on one topic",
        "operationId": "getReceiptsByTopic",
        "parameters": [
          {
            "name": "topic",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 100
            },
            "description": "A topic slug from `/api/receipts/topics`."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "description": "Page size. Values outside 1 to 100 are clamped."
          }
        ],
        "responses": {
          "200": {
            "description": "Contradictions, most confident first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ReceiptWithContext"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/CountMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/receipts/{postId}": {
      "get": {
        "tags": [
          "Receipts"
        ],
        "summary": "Contradictions involving one post",
        "description": "Each from this post's side: `claimText` is what this post said, `contradictingClaimText` what the other post said, and `direction` whether the other came earlier or later.",
        "operationId": "getReceiptsForPost",
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Post ID: `ts_` and the Truth Social status id, or `x_` and the tweet id."
          }
        ],
        "responses": {
          "200": {
            "description": "The post's contradictions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Receipt"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/CountMeta"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/sync": {
      "post": {
        "tags": [
          "Sync"
        ],
        "summary": "Sync from Truth Social",
        "description": "Operator only. Pulls the latest posts from Truth Social. Requires Bearer token authorization.",
        "operationId": "triggerSync",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sync result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    },
    "headers": {
      "X-RateLimit-Limit": {
        "description": "Requests allowed in the window",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Requests left in the window",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Reset": {
        "description": "When the window resets, in Unix seconds",
        "schema": {
          "type": "integer"
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before trying again",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "A parameter is missing or can't be read",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Nothing archived under that ID or date",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests from this IP in the last minute",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Post": {
        "type": "object",
        "required": [
          "id",
          "platform",
          "platformId",
          "content",
          "contentHtml",
          "createdAt",
          "isRepost",
          "mediaUrls",
          "mediaTypes",
          "externalMetrics",
          "checksum"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "ts_114027960288516270"
            ]
          },
          "platform": {
            "type": "string",
            "enum": [
              "twitter",
              "truth"
            ]
          },
          "platformId": {
            "type": "string"
          },
          "content": {
            "type": "string",
            "description": "The post's own text. Empty for a post that is only media; its words, if any, are in `transcripts`."
          },
          "contentHtml": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the platform stopped serving the post, once confirmed gone. The archive keeps it."
          },
          "isRepost": {
            "type": "boolean"
          },
          "repostOfId": {
            "type": [
              "string",
              "null"
            ]
          },
          "replyToId": {
            "type": [
              "string",
              "null"
            ]
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "mediaTypes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "image",
                "video",
                "gif"
              ]
            }
          },
          "externalMetrics": {
            "$ref": "#/components/schemas/ExternalMetrics"
          },
          "audioUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "Narration mp3: a synthesized voice reading the post text, not a recording of anyone."
          },
          "audioGeneratedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "audioStatus": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "skip",
              "failed",
              null
            ]
          },
          "audioSize": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Narration size in bytes"
          },
          "audioDuration": {
            "type": [
              "number",
              "null"
            ],
            "description": "Narration length in seconds"
          },
          "checksum": {
            "type": "string"
          },
          "commentaryId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set when the post has an analysis, at /api/analysis/{id} and https://trump.fm/post/{id}/analysis."
          },
          "commentaryDangerLevel": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "none",
              "elevated",
              "high",
              "critical",
              null
            ]
          },
          "repostOf": {
            "description": "The post this one reposts, when the archive holds it. A repost wrapper's own content is often just a bare mention, so this is where the reposted words and media are. One level deep: this post's own repostOf is never populated.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/Post"
              },
              {
                "type": "null"
              }
            ]
          },
          "repostSource": {
            "description": "What was recovered of a reposted post by an account the archive doesn't hold.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/RepostSource"
              },
              {
                "type": "null"
              }
            ]
          },
          "transcripts": {
            "description": "Machine transcripts of the post's video and descriptions of its images. Absent when there are none.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MediaTranscript"
            }
          },
          "matchContext": {
            "description": "On search results only: where the match was when it wasn't the post's own text.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MatchContext"
            }
          }
        }
      },
      "ExternalMetrics": {
        "type": "object",
        "required": [
          "likes",
          "reposts",
          "replies",
          "views",
          "fetchedAt"
        ],
        "properties": {
          "likes": {
            "type": "integer"
          },
          "reposts": {
            "type": "integer"
          },
          "replies": {
            "type": "integer"
          },
          "views": {
            "type": [
              "integer",
              "null"
            ]
          },
          "fetchedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "RepostSource": {
        "type": "object",
        "required": [
          "postId",
          "sourcePlatform",
          "content",
          "status"
        ],
        "properties": {
          "postId": {
            "type": "string"
          },
          "sourcePlatform": {
            "type": "string"
          },
          "sourceId": {
            "type": [
              "string",
              "null"
            ]
          },
          "sourceUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "authorHandle": {
            "type": [
              "string",
              "null"
            ]
          },
          "authorName": {
            "type": [
              "string",
              "null"
            ]
          },
          "authorAvatarUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "content": {
            "type": "string"
          },
          "contentHtml": {
            "type": [
              "string",
              "null"
            ]
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "mediaTypes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "image",
                "video",
                "gif"
              ]
            }
          },
          "sourceCreatedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "parsed",
              "hydrated",
              "unavailable",
              "failed"
            ],
            "description": "`parsed` came out of the repost's own text, `hydrated` was refetched from the platform."
          }
        }
      },
      "MediaTranscript": {
        "type": "object",
        "description": "One attachment's words. A video carries `transcript`, an image `description`. Both are machine output and can be wrong about names and numbers.",
        "required": [
          "id",
          "postId",
          "origin",
          "mediaUrl",
          "mediaType",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "postId": {
            "type": "string"
          },
          "origin": {
            "type": "string",
            "enum": [
              "post",
              "repost"
            ]
          },
          "mediaUrl": {
            "type": "string"
          },
          "mediaType": {
            "type": "string",
            "enum": [
              "image",
              "video",
              "gif"
            ]
          },
          "durationSeconds": {
            "type": [
              "number",
              "null"
            ]
          },
          "transcript": {
            "type": [
              "string",
              "null"
            ]
          },
          "segments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TranscriptSegment"
            }
          },
          "lang": {
            "type": [
              "string",
              "null"
            ]
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "done",
              "failed",
              "skipped"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "descriptionOcr": {
            "type": [
              "string",
              "null"
            ],
            "description": "Text read off the image, verbatim"
          },
          "descriptionKind": {
            "type": [
              "string",
              "null"
            ],
            "examples": [
              "photo",
              "meme",
              "screenshot",
              "chart",
              "document"
            ]
          }
        }
      },
      "TranscriptSegment": {
        "type": "object",
        "required": [
          "from",
          "to",
          "text"
        ],
        "properties": {
          "from": {
            "type": "integer",
            "description": "Offset in milliseconds"
          },
          "to": {
            "type": "integer",
            "description": "Offset in milliseconds"
          },
          "text": {
            "type": "string"
          }
        }
      },
      "MatchContext": {
        "type": "object",
        "required": [
          "kind",
          "snippet"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "transcript",
              "repost",
              "image"
            ]
          },
          "snippet": {
            "type": "string",
            "description": "HTML-escaped excerpt with <mark> around the match"
          }
        }
      },
      "MatchCount": {
        "type": "object",
        "required": [
          "period",
          "count",
          "twitter",
          "truth"
        ],
        "properties": {
          "period": {
            "type": "string",
            "description": "YYYY, or YYYY-MM when counted by month"
          },
          "count": {
            "type": "integer",
            "minimum": 1
          },
          "twitter": {
            "type": "integer",
            "minimum": 0
          },
          "truth": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "LatestSync": {
        "type": "object",
        "properties": {
          "postId": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "syncedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Stats": {
        "type": "object",
        "properties": {
          "totalPosts": {
            "type": "integer"
          },
          "twitterPosts": {
            "type": "integer"
          },
          "truthPosts": {
            "type": "integer"
          },
          "deletedPosts": {
            "type": "integer"
          },
          "postsWithAudio": {
            "type": "integer"
          },
          "postsWithAnalysis": {
            "type": "integer"
          },
          "daysWithAnalysis": {
            "type": "integer"
          }
        }
      },
      "Commentary": {
        "type": "object",
        "required": [
          "id",
          "postId",
          "content",
          "dangerLevel",
          "generatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "postId": {
            "type": "string"
          },
          "content": {
            "type": "string",
            "description": "Markdown body"
          },
          "summary": {
            "type": [
              "string",
              "null"
            ]
          },
          "authorshipScore": {
            "type": "number"
          },
          "authorshipConfidence": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ]
          },
          "authorshipIndicators": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "psychologicalProfile": {
            "type": "object"
          },
          "cognitiveMarkers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "cognitiveComplexity": {
            "type": [
              "number",
              "null"
            ]
          },
          "baselineDeviation": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "none",
              "slight",
              "moderate",
              "significant",
              null
            ]
          },
          "rhetoricalDevices": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "dehumanizingLanguage": {
            "type": "boolean"
          },
          "violentImagery": {
            "type": "boolean"
          },
          "dangerLevel": {
            "type": "string",
            "enum": [
              "none",
              "elevated",
              "high",
              "critical"
            ]
          },
          "dangerIndicators": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "stochasticTerrorism": {
            "type": "boolean"
          },
          "gaslightingPresent": {
            "type": "boolean"
          },
          "gaslightingIndicators": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "realityDistortions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "epistemicClosure": {
            "type": "boolean"
          },
          "hypomanicState": {
            "type": "string",
            "enum": [
              "absent",
              "mild",
              "moderate",
              "marked"
            ]
          },
          "hypomanicIndicators": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "deteriorationTrajectory": {
            "type": "string",
            "enum": [
              "stable",
              "improving",
              "declining"
            ]
          },
          "baselineComparison": {
            "type": [
              "string",
              "null"
            ]
          },
          "veracityScore": {
            "type": [
              "number",
              "null"
            ]
          },
          "factChecks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FactCheck"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WeightedTag"
            }
          },
          "sentimentScore": {
            "type": "number"
          },
          "intensityScore": {
            "type": "number"
          },
          "relatedPostIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "eventIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "flags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "receipts": {
            "description": "Contradictions involving this post",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Receipt"
            }
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "reverifiedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When reverification last ran: it retries the unverifiable fact checks in place, and stamps this even when nothing changed"
          }
        }
      },
      "DailyDigest": {
        "type": "object",
        "required": [
          "id",
          "date",
          "postCount",
          "content",
          "summary",
          "headline",
          "generatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "postCount": {
            "type": "integer"
          },
          "postIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "commentaryIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "content": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "headline": {
            "type": "string"
          },
          "dominantState": {
            "type": "string",
            "enum": [
              "grandiose",
              "vulnerable",
              "mixed",
              "stable",
              "unknown"
            ]
          },
          "stateTransitions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StateTransition"
            }
          },
          "aggregateRageLevel": {
            "type": "number"
          },
          "peakRagePostId": {
            "type": [
              "string",
              "null"
            ]
          },
          "escalationDetected": {
            "type": "boolean"
          },
          "escalationPattern": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "startPostId": {
                "type": "string"
              },
              "peakPostId": {
                "type": "string"
              },
              "trajectory": {
                "type": "string",
                "enum": [
                  "rapid",
                  "gradual",
                  "spike"
                ]
              },
              "durationMinutes": {
                "type": "integer"
              },
              "peakIntensity": {
                "type": "number"
              }
            }
          },
          "dominantThemes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThemeOccurrence"
            }
          },
          "themeObsession": {
            "type": "boolean"
          },
          "obsessionTopic": {
            "type": [
              "string",
              "null"
            ]
          },
          "contradictions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Contradiction"
            }
          },
          "postFrequencyPercentile": {
            "type": [
              "number",
              "null"
            ]
          },
          "avgTimeBetweenPosts": {
            "type": [
              "number",
              "null"
            ]
          },
          "earliestPostTime": {
            "type": [
              "string",
              "null"
            ]
          },
          "latestPostTime": {
            "type": [
              "string",
              "null"
            ]
          },
          "sleepDeprivationLikely": {
            "type": "boolean"
          },
          "hypomanicEpisode": {
            "type": "boolean"
          },
          "narrativeArc": {
            "type": "string",
            "enum": [
              "contamination",
              "redemption",
              "chaos",
              "stable",
              "mixed"
            ]
          },
          "narrativeSummary": {
            "type": "string"
          },
          "triggeringEvents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventTrigger"
            }
          },
          "maxDangerLevel": {
            "type": "string",
            "enum": [
              "none",
              "elevated",
              "high",
              "critical"
            ]
          },
          "dangerPostIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "stochasticTerrorismPattern": {
            "type": "boolean"
          },
          "cognitiveConcerns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "complexityTrend": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "declining",
              "stable",
              "improving",
              null
            ]
          },
          "claimsCount": {
            "type": "integer"
          },
          "falseClaimsCount": {
            "type": "integer"
          },
          "veracityScoreAvg": {
            "type": [
              "number",
              "null"
            ]
          },
          "era": {
            "type": "string"
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "DigestSummary": {
        "type": "object",
        "required": [
          "date",
          "headline",
          "summary",
          "postCount"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "headline": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "postCount": {
            "type": "integer"
          },
          "maxDangerLevel": {
            "type": "string",
            "enum": [
              "none",
              "elevated",
              "high",
              "critical"
            ]
          },
          "dominantState": {
            "type": "string"
          },
          "era": {
            "type": "string"
          }
        }
      },
      "Receipt": {
        "type": "object",
        "required": [
          "id",
          "claimText",
          "contradictingClaimText",
          "contradictingPostId",
          "severity",
          "confidence",
          "explanation",
          "topic",
          "daysApart",
          "direction"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "claimText": {
            "type": "string"
          },
          "contradictingClaimText": {
            "type": "string"
          },
          "contradictingPostId": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "enum": [
              "reversal",
              "major",
              "moderate",
              "minor"
            ]
          },
          "confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "explanation": {
            "type": "string"
          },
          "topic": {
            "type": "string"
          },
          "daysApart": {
            "type": "integer"
          },
          "direction": {
            "type": "string",
            "enum": [
              "earlier",
              "later"
            ],
            "description": "When the contradicting post came, relative to this one"
          },
          "postCreatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "contradictingPostCreatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ReceiptWithContext": {
        "description": "A contradiction read from `postId`'s side, with when it was found.",
        "allOf": [
          {
            "$ref": "#/components/schemas/Receipt"
          },
          {
            "type": "object",
            "required": [
              "postId",
              "detectedAt"
            ],
            "properties": {
              "postId": {
                "type": "string"
              },
              "detectedAt": {
                "type": "string"
              }
            }
          }
        ]
      },
      "ReceiptTopic": {
        "type": "object",
        "required": [
          "topic",
          "count"
        ],
        "properties": {
          "topic": {
            "type": "string"
          },
          "count": {
            "type": "integer"
          }
        }
      },
      "WeightedTag": {
        "type": "object",
        "required": [
          "tag",
          "weight"
        ],
        "properties": {
          "tag": {
            "type": "string"
          },
          "weight": {
            "type": "number"
          },
          "category": {
            "type": "string"
          }
        }
      },
      "FactCheck": {
        "type": "object",
        "required": [
          "claim",
          "verdict",
          "evidence",
          "sources"
        ],
        "properties": {
          "claim": {
            "type": "string"
          },
          "verdict": {
            "type": "string",
            "enum": [
              "true",
              "mostly true",
              "half true",
              "mostly false",
              "false",
              "unverifiable"
            ]
          },
          "evidence": {
            "type": "string"
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "StateTransition": {
        "type": "object",
        "required": [
          "time",
          "postId",
          "fromState",
          "toState"
        ],
        "properties": {
          "time": {
            "type": "string"
          },
          "postId": {
            "type": "string"
          },
          "fromState": {
            "type": "string"
          },
          "toState": {
            "type": "string"
          },
          "trigger": {
            "type": "string"
          }
        }
      },
      "ThemeOccurrence": {
        "type": "object",
        "required": [
          "theme",
          "frequency",
          "postIds"
        ],
        "properties": {
          "theme": {
            "type": "string"
          },
          "frequency": {
            "type": "integer"
          },
          "postIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Contradiction": {
        "type": "object",
        "required": [
          "postId1",
          "postId2",
          "claim1",
          "claim2"
        ],
        "properties": {
          "postId1": {
            "type": "string"
          },
          "postId2": {
            "type": "string"
          },
          "claim1": {
            "type": "string"
          },
          "claim2": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "enum": [
              "minor",
              "moderate",
              "major"
            ]
          }
        }
      },
      "EventTrigger": {
        "type": "object",
        "required": [
          "eventTitle",
          "responsePostIds"
        ],
        "properties": {
          "eventId": {
            "type": "string"
          },
          "eventTitle": {
            "type": "string"
          },
          "responsePostIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "reactionType": {
            "type": "string",
            "enum": [
              "defensive",
              "offensive",
              "dismissive",
              "amplifying"
            ]
          }
        }
      },
      "CursorMeta": {
        "type": "object",
        "properties": {
          "cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "hasMore": {
            "type": "boolean"
          }
        }
      },
      "OffsetMeta": {
        "type": "object",
        "properties": {
          "offset": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "hasMore": {
            "type": "boolean"
          }
        }
      },
      "CountMeta": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "message",
              "code"
            ],
            "properties": {
              "message": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "details": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "path": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}