{
  "openapi": "3.1.0",
  "info": {
    "title": "StartupXO public read API",
    "version": "1.0.0",
    "description": "Read-only, no key, CORS enabled. Every list and post is also available as Markdown at /{lang}/index.md, /{lang}/{new|best|ask|show|jobs}.md and /{lang}/{id}.md. Responses are cached for about a minute; please keep requests under one per second.",
    "contact": {
      "email": "hello@startupxo.com"
    }
  },
  "servers": [
    {
      "url": "https://startupxo.com"
    }
  ],
  "paths": {
    "/api/v1/front.json": {
      "get": {
        "operationId": "list_front",
        "summary": "Front page, ranked by votes, independent commenters and age",
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Reading language. Titles, summaries and comments come in this language when a checked translation exists.",
            "schema": {
              "type": "string",
              "enum": [
                "ko",
                "en",
                "ja",
                "es",
                "ar"
              ],
              "default": "ko"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number, 30 items per page, up to 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoryList"
                }
              }
            }
          },
          "503": {
            "description": "Database temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/new.json": {
      "get": {
        "operationId": "list_new",
        "summary": "Newest posts",
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Reading language. Titles, summaries and comments come in this language when a checked translation exists.",
            "schema": {
              "type": "string",
              "enum": [
                "ko",
                "en",
                "ja",
                "es",
                "ar"
              ],
              "default": "ko"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number, 30 items per page, up to 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoryList"
                }
              }
            }
          },
          "503": {
            "description": "Database temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/best.json": {
      "get": {
        "operationId": "list_best",
        "summary": "Best of the past 7 days",
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Reading language. Titles, summaries and comments come in this language when a checked translation exists.",
            "schema": {
              "type": "string",
              "enum": [
                "ko",
                "en",
                "ja",
                "es",
                "ar"
              ],
              "default": "ko"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number, 30 items per page, up to 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoryList"
                }
              }
            }
          },
          "503": {
            "description": "Database temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ask.json": {
      "get": {
        "operationId": "list_ask",
        "summary": "Ask XO questions",
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Reading language. Titles, summaries and comments come in this language when a checked translation exists.",
            "schema": {
              "type": "string",
              "enum": [
                "ko",
                "en",
                "ja",
                "es",
                "ar"
              ],
              "default": "ko"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number, 30 items per page, up to 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoryList"
                }
              }
            }
          },
          "503": {
            "description": "Database temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/show.json": {
      "get": {
        "operationId": "list_show",
        "summary": "Show XO projects",
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Reading language. Titles, summaries and comments come in this language when a checked translation exists.",
            "schema": {
              "type": "string",
              "enum": [
                "ko",
                "en",
                "ja",
                "es",
                "ar"
              ],
              "default": "ko"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number, 30 items per page, up to 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoryList"
                }
              }
            }
          },
          "503": {
            "description": "Database temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs.json": {
      "get": {
        "operationId": "list_jobs",
        "summary": "Job XO posts",
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Reading language. Titles, summaries and comments come in this language when a checked translation exists.",
            "schema": {
              "type": "string",
              "enum": [
                "ko",
                "en",
                "ja",
                "es",
                "ar"
              ],
              "default": "ko"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number, 30 items per page, up to 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoryList"
                }
              }
            }
          },
          "503": {
            "description": "Database temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/item.json": {
      "get": {
        "operationId": "get_item",
        "summary": "One post with its summary, sources and nested comment thread",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Reading language. Titles, summaries and comments come in this language when a checked translation exists.",
            "schema": {
              "type": "string",
              "enum": [
                "ko",
                "en",
                "ja",
                "es",
                "ar"
              ],
              "default": "ko"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Item"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Database temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/user.json": {
      "get": {
        "operationId": "get_user",
        "summary": "Public profile and submitted posts, newest first",
        "parameters": [
          {
            "name": "handle",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 40
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Reading language. Titles, summaries and comments come in this language when a checked translation exists.",
            "schema": {
              "type": "string",
              "enum": [
                "ko",
                "en",
                "ja",
                "es",
                "ar"
              ],
              "default": "ko"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number, 30 items per page, up to 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Database temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search.json": {
      "get": {
        "operationId": "search",
        "summary": "Search titles, summaries, text and sites",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 80
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "story",
                "ask",
                "show",
                "job"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "newest",
                "points"
              ],
              "default": "newest"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "enum": [
                7,
                30,
                365
              ]
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Reading language. Titles, summaries and comments come in this language when a checked translation exists.",
            "schema": {
              "type": "string",
              "enum": [
                "ko",
                "en",
                "ja",
                "es",
                "ar"
              ],
              "default": "ko"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number, 30 items per page, up to 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Database temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Story": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "title",
          "by",
          "score",
          "comments",
          "time",
          "discussion"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "kind": {
            "type": "string",
            "enum": [
              "story",
              "ask",
              "show",
              "job"
            ]
          },
          "title": {
            "type": "string",
            "description": "Ask, show and job posts carry an 'Ask XO:', 'Show XO:' or 'Job XO:' prefix."
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Original link. Null for text posts."
          },
          "host": {
            "type": [
              "string",
              "null"
            ]
          },
          "by": {
            "type": "string"
          },
          "score": {
            "type": "integer",
            "description": "Votes. Posts by people start at 1, collected posts at 0."
          },
          "comments": {
            "type": "integer",
            "description": "Live comments, including editorial notes."
          },
          "editorial_comments": {
            "type": "integer",
            "description": "Comments by the editorial account (the O and X note)."
          },
          "time": {
            "type": "string",
            "format": "date-time"
          },
          "origin": {
            "type": "string",
            "enum": [
              "community",
              "curated",
              "archive"
            ],
            "description": "community = posted by a person, curated = collected and summarized automatically."
          },
          "language": {
            "type": "object",
            "properties": {
              "source": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "reading": {
                "type": "string"
              },
              "translated": {
                "type": "boolean"
              }
            }
          },
          "summary": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Two to five fact lines checked against the source."
          },
          "discussion": {
            "type": "string",
            "format": "uri"
          },
          "markdown": {
            "type": "string",
            "format": "uri"
          },
          "api": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "StoryList": {
        "type": "object",
        "properties": {
          "list": {
            "type": "string",
            "enum": [
              "front",
              "new",
              "best",
              "ask",
              "show",
              "jobs"
            ]
          },
          "lang": {
            "type": "string"
          },
          "page": {
            "type": "integer"
          },
          "has_more": {
            "type": "boolean"
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "html": {
            "type": "string",
            "format": "uri"
          },
          "markdown": {
            "type": "string",
            "format": "uri"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Story"
            }
          }
        }
      },
      "Comment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "by": {
            "type": [
              "string",
              "null"
            ]
          },
          "score": {
            "type": "integer"
          },
          "time": {
            "type": "string",
            "format": "date-time"
          },
          "text": {
            "type": [
              "string",
              "null"
            ],
            "description": "Plain text with line breaks. Null when removed."
          },
          "editorial": {
            "type": "boolean"
          },
          "removed": {
            "type": "boolean",
            "description": "Present when the comment was removed but still has visible replies."
          },
          "replies": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Comment"
            }
          }
        }
      },
      "Item": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Story"
          },
          {
            "type": "object",
            "properties": {
              "text": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "edited": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "sources": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "site": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "score": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "comments": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "observed_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              },
              "thread": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Comment"
                }
              }
            }
          }
        ]
      },
      "User": {
        "type": "object",
        "properties": {
          "handle": {
            "type": "string"
          },
          "karma": {
            "type": "integer"
          },
          "about": {
            "type": [
              "string",
              "null"
            ]
          },
          "created": {
            "type": "string",
            "format": "date-time"
          },
          "posts": {
            "type": "integer"
          },
          "comments": {
            "type": "integer"
          },
          "html": {
            "type": "string",
            "format": "uri"
          },
          "page": {
            "type": "integer"
          },
          "has_more": {
            "type": "boolean"
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "submitted": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Story"
            }
          }
        }
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "lang": {
            "type": "string"
          },
          "page": {
            "type": "integer"
          },
          "has_more": {
            "type": "boolean"
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Story"
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          }
        }
      }
    }
  }
}