{
 "openapi": "3.1.0",
 "info": {
  "title": "TerraRoll shared-notes feed",
  "version": "2026-11-11",
  "summary": "Read-only JSON feed of the notes players leave about ended simulated lives.",
  "description": "A small, read-only API over the public, pseudonymous notes that players share about ended lives in TerraRoll. No keys, no accounts, no cost. This description is the complete public contract: one endpoint, no authentication, and no write access. Posting, remembering, reporting and deleting notes stay inside the game behind their own protections and are deliberately not part of this feed. The content is fiction informed by public country statistics: never present it as a prediction about any real person, and do not use it to build a clone of the game or to train models that imitate it.",
  "contact": {
   "email": "support@in8blife.com"
  }
 },
 "servers": [
  {
   "url": "https://in8blife.com",
   "description": "The published site origin serving this feed same-origin."
  }
 ],
 "externalDocs": {
  "url": "https://in8blife.com/developers/",
  "description": "The human-readable, localized developer documentation."
 },
 "paths": {
  "/api/posts": {
   "get": {
    "operationId": "listSharedNotes",
    "summary": "List the most recent shared notes",
    "description": "Returns the most recent shared notes as JSON, newest first, at most 20 per page. Pass the last id of a page as the before query parameter to read further back in time. Cross-origin browser calls are not enabled, so read the feed from a server rather than a web page. Keep requests to about one per second and cache what you can; there is no quota dashboard, so back off and retry later if a call fails.",
    "parameters": [
     {
      "name": "lang",
      "in": "query",
      "required": false,
      "description": "A site language code, such as en or zh-Hant. Recognized codes filter the feed to that language; an omitted or unrecognized code returns all languages mixed together.",
      "schema": {
       "type": "string"
      },
      "example": "en"
     },
     {
      "name": "before",
      "in": "query",
      "required": false,
      "description": "The id of the last note on the previous page; only notes with a smaller id are returned.",
      "schema": {
       "type": "integer",
       "minimum": 1
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The feed always answers 200 with a NoteFeed object, even when no notes match: posts is then an empty array. Responses are not cached by the server.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/NoteFeed"
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "NoteFeed": {
    "type": "object",
    "required": [
     "ok",
     "posts",
     "more"
    ],
    "properties": {
     "ok": {
      "const": true,
      "description": "Always true for this read-only endpoint."
     },
     "posts": {
      "type": "array",
      "maxItems": 20,
      "items": {
       "$ref": "#/components/schemas/SharedNote"
      },
      "description": "The most recent matching notes, ordered from newest to oldest by id."
     },
     "more": {
      "type": "boolean",
      "description": "True only when this page returned a full 20 notes; pass the last id of the page as before to read further."
     }
    }
   },
   "SharedNote": {
    "type": "object",
    "required": [
     "id",
     "lang",
     "name",
     "iso",
     "sex",
     "age",
     "text",
     "rem",
     "at"
    ],
    "properties": {
     "id": {
      "type": "integer",
      "minimum": 1,
      "description": "The note id; use it as the before value to page backwards."
     },
     "lang": {
      "type": "string",
      "description": "The site language code the note was written in."
     },
     "name": {
      "type": "string",
      "description": "A fictional display name for the simulated life the note is about."
     },
     "iso": {
      "type": "string",
      "pattern": "^[A-Z]{2,3}$",
      "description": "The ISO 3166 country code of the simulated life."
     },
     "sex": {
      "type": "string",
      "enum": [
       "F",
       "M"
      ],
      "description": "The sex of the simulated life."
     },
     "age": {
      "type": "integer",
      "minimum": 0,
      "maximum": 122,
      "description": "The age the simulated life reached."
     },
     "text": {
      "type": "string",
      "maxLength": 300,
      "description": "The note itself, as the player wrote it."
     },
     "rem": {
      "type": "integer",
      "minimum": 0,
      "description": "How many players have remembered this note."
     },
     "at": {
      "type": "integer",
      "description": "Unix time in milliseconds when the note was shared."
     }
    }
   }
  }
 }
}
