diff --git a/.github/workflows/fuzz-nightly.yml b/.github/workflows/fuzz-nightly.yml new file mode 100644 index 0000000..aa87150 --- /dev/null +++ b/.github/workflows/fuzz-nightly.yml @@ -0,0 +1,137 @@ +name: fuzz-nightly + +on: + schedule: + - cron: '0 18 * * *' # 18:00 UTC = 02:00 China next day + workflow_dispatch: + inputs: + budget: + description: 'Fuzz budget in seconds' + required: false + default: '600' + +permissions: + contents: read + issues: write + +jobs: + fuzz: + runs-on: ubuntu-22.04 + env: + OPENRESTY_PREFIX: "/usr/local/openresty" + FUZZ_BUDGET: ${{ github.event.inputs.budget || '600' }} + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential libncurses5-dev libreadline-dev libssl-dev perl lua5.1 liblua5.1-0-dev + + - name: Install OpenResty + run: | + wget -qO - https://openresty.org/package/pubkey.gpg | sudo gpg --dearmor -o /usr/share/keyrings/openresty.gpg + echo "deb [signed-by=/usr/share/keyrings/openresty.gpg] http://openresty.org/package/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/openresty.list + sudo apt-get update + sudo apt-get install -y openresty + + - name: Install LuaRocks + run: | + LUAROCKS_VER=3.12.0 + wget -q "https://github.com/luarocks/luarocks/archive/v${LUAROCKS_VER}.tar.gz" + tar xzf "v${LUAROCKS_VER}.tar.gz" + cd "luarocks-${LUAROCKS_VER}" + ./configure --with-lua=$OPENRESTY_PREFIX/luajit + make build && sudo make install + cd .. && rm -rf "luarocks-${LUAROCKS_VER}" "v${LUAROCKS_VER}.tar.gz" + + # Configure OpenSSL paths for rocks that need it + OPENSSL_PREFIX=$OPENRESTY_PREFIX/openssl3 + if [ ! -d "$OPENSSL_PREFIX" ]; then + OPENSSL_PREFIX=$OPENRESTY_PREFIX/openssl111 + fi + if [ ! -d "$OPENSSL_PREFIX" ]; then + OPENSSL_PREFIX=$OPENRESTY_PREFIX/openssl + fi + if [ -d "$OPENSSL_PREFIX" ]; then + luarocks config variables.OPENSSL_LIBDIR ${OPENSSL_PREFIX}/lib + luarocks config variables.OPENSSL_INCDIR ${OPENSSL_PREFIX}/include + fi + + - name: Install Lua dependencies + run: | + sudo luarocks install jsonschema + sudo luarocks install lua-resty-radixtree + + - name: Run mutation fuzzer + id: fuzz + continue-on-error: true + run: | + export PATH=$OPENRESTY_PREFIX/nginx/sbin:$OPENRESTY_PREFIX/bin:$PATH + case "$FUZZ_BUDGET" in + ''|*[!0-9]*) + echo "FUZZ_BUDGET must be an integer number of seconds" >&2 + exit 2 + ;; + esac + make fuzz "FUZZ_BUDGET=$FUZZ_BUDGET" + + - name: Upload findings + if: steps.fuzz.outcome == 'failure' + uses: actions/upload-artifact@v4 + with: + name: fuzz-findings-${{ github.run_id }} + path: fuzz/out/ + retention-days: 90 + + - name: Open / update tracking issue + if: steps.fuzz.outcome == 'failure' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + DATE=$(date -u +%Y-%m-%d) + TITLE="Nightly fuzz failure: $DATE" + RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + SUMMARY=$(cat fuzz/out/summary.json 2>/dev/null || echo '{}') + FIRST5=$(head -n 5 fuzz/out/crashes.jsonl 2>/dev/null || echo '(no crashes.jsonl found)') + BODY=$(cat </dev/null || true + gh issue create --title "$TITLE" \ + --label fuzz-nightly,bug \ + --assignee jarvis9443 \ + --body "$BODY" + fi + + - name: Fail the job if fuzz failed + if: steps.fuzz.outcome == 'failure' + run: exit 1 diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml new file mode 100644 index 0000000..75123a8 --- /dev/null +++ b/.github/workflows/fuzz.yml @@ -0,0 +1,71 @@ +name: fuzz + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + fuzz: + runs-on: ubuntu-22.04 + env: + OPENRESTY_PREFIX: "/usr/local/openresty" + FUZZ_BUDGET: "120" + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential libncurses5-dev libreadline-dev libssl-dev perl lua5.1 liblua5.1-0-dev + + - name: Install OpenResty + run: | + wget -qO - https://openresty.org/package/pubkey.gpg | sudo gpg --dearmor -o /usr/share/keyrings/openresty.gpg + echo "deb [signed-by=/usr/share/keyrings/openresty.gpg] http://openresty.org/package/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/openresty.list + sudo apt-get update + sudo apt-get install -y openresty + + - name: Install LuaRocks + run: | + LUAROCKS_VER=3.12.0 + wget -q "https://github.com/luarocks/luarocks/archive/v${LUAROCKS_VER}.tar.gz" + tar xzf "v${LUAROCKS_VER}.tar.gz" + cd "luarocks-${LUAROCKS_VER}" + ./configure --with-lua=$OPENRESTY_PREFIX/luajit + make build && sudo make install + cd .. && rm -rf "luarocks-${LUAROCKS_VER}" "v${LUAROCKS_VER}.tar.gz" + + # Configure OpenSSL paths for rocks that need it + OPENSSL_PREFIX=$OPENRESTY_PREFIX/openssl3 + if [ ! -d "$OPENSSL_PREFIX" ]; then + OPENSSL_PREFIX=$OPENRESTY_PREFIX/openssl111 + fi + if [ ! -d "$OPENSSL_PREFIX" ]; then + OPENSSL_PREFIX=$OPENRESTY_PREFIX/openssl + fi + if [ -d "$OPENSSL_PREFIX" ]; then + luarocks config variables.OPENSSL_LIBDIR ${OPENSSL_PREFIX}/lib + luarocks config variables.OPENSSL_INCDIR ${OPENSSL_PREFIX}/include + fi + + - name: Install Lua dependencies + run: | + sudo luarocks install jsonschema + sudo luarocks install lua-resty-radixtree + + - name: Run mutation fuzzer + run: | + export PATH=$OPENRESTY_PREFIX/nginx/sbin:$OPENRESTY_PREFIX/bin:$PATH + make fuzz FUZZ_BUDGET=$FUZZ_BUDGET + + - name: Upload findings + if: failure() + uses: actions/upload-artifact@v4 + with: + name: fuzz-findings-${{ github.run_id }} + path: fuzz/out/ + retention-days: 30 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..879a644 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +fuzz/__pycache__/ diff --git a/Makefile b/Makefile index 515b8c9..09e45e5 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,11 @@ test-conformance: lint: luacheck -q lib/ +### fuzz: Run mutation fuzzer (FUZZ_BUDGET seconds, default 60) +FUZZ_BUDGET ?= 60 +fuzz: + python3 fuzz/mutate_fuzz.py --budget $(FUZZ_BUDGET) --out fuzz/out + ### clean: Remove build artifacts clean: - rm -rf *.rock + rm -rf *.rock fuzz/out diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 0000000..76f981f --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,2 @@ +out/ +out_*/ diff --git a/fuzz/README.md b/fuzz/README.md new file mode 100644 index 0000000..e56d35b --- /dev/null +++ b/fuzz/README.md @@ -0,0 +1,86 @@ +# Mutation Fuzzer for `lua-resty-openapi-validator` + +A small mutation fuzzer that runs the validator against AST-mutated copies of +real-world OpenAPI specs and checks two oracles: + +1. **No crashes**: `validate_request` must not throw a Lua error + (caught with `pcall`). +2. **Schema conformance**: a request **generated to satisfy** an operation's + schema must be **accepted** by the validator. A rejection is a candidate + false-negative bug. + +The fuzzer is the productionised form of the harness used during v1.0.3 QA. +It reproduces the bugs that QA found (path-extension Bug 1 against the +unfixed validator, `utf8_len(table)` Bug 3 against the unfixed jsonschema). + +## Architecture + +```text +mutate_fuzz.py (Python orchestrator) + ├─ pick a seed spec from fuzz/seeds/ + ├─ apply N random mutations (mutators below) + ├─ generate schema-conforming positive requests + └─ resty -e RUNNER_LUA (validator subprocess, one per round) + └─ for each case: pcall(v:validate_request, req) + └─ JSONL result on stdout: {phase, accepted, err} +``` + +Mutators (`fuzz/mutate_fuzz.py`): + +| name | what it does | targets | +|---|---|---| +| `path_extension` | append `.json` / `.xml` / `.txt` / `.v2` to a random path | path-routing edge cases (Bug 1) | +| `nullable_enum` | inject `null` into an enum + flip `nullable: true` | nullable-enum handling (Bug 2) | +| `length_on_array` | move `maxLength` onto an `array` schema | type-inappropriate keywords (Bug 3) | +| `param_style` | flip parameter `style`/`explode` | parameter parsing (Bug 4 family) | +| `required_phantom` | add a non-existent property name to `required` | schema-validation edge cases | +| `swap_scalar_type` | swap `type: integer` ↔ `type: string` | coercion paths | + +Generator (`sample_value`): produces JSON values that match a JSON Schema +fragment (string / integer / number / boolean / array / object / enum), with +a depth limit. Path/query/header parameters that are `required: true` are +filled in; the request body is sampled from the operation's +`requestBody` schema if present. + +## Run locally + +```bash +make fuzz # 60s budget +make fuzz FUZZ_BUDGET=300 # 5 min +python3 fuzz/mutate_fuzz.py --budget 60 --seed 7 # reproducible +``` + +Output: + +- `fuzz/out/crashes.jsonl` — one JSON object per finding +- `fuzz/out/summary.json` — `{rounds, cases_run, elapsed_s, crash_count, false_negative_count, total_findings}` +- exits non-zero on any crash or candidate false-negative (CI-friendly) + +## Add a seed + +Drop any OpenAPI 3.x spec into `fuzz/seeds/`. Smaller specs (50–100 ops) +give more mutation rounds per second; very large specs (>500 ops) slow +each round. Recommended size: 30 KB – 300 KB. + +## Add a mutator + +1. Add `def my_mutator(spec, rng): ...` near the other mutators. +2. Append `("name", my_mutator)` to the `MUTATORS` list. +3. Mutator must mutate `spec` **in place** and return `True` if a mutation + was applied, `False` otherwise. The label is taken from the tuple name. + +## Noise filter + +`gen_cases` does not try to satisfy every JSON Schema construct — `oneOf` / +`allOf` / `discriminator` / complex `pattern` are common in real specs but +hard to satisfy generically. Errors mentioning these are filtered as +generator artefacts, not validator bugs. The list lives near the bottom +of `mutate_fuzz.py`. If the filter masks a real bug you find by other +means, narrow / shrink it; if it lets through too much noise, widen it. + +## CI + +- **PR**: `.github/workflows/fuzz.yml` — 120s budget, fails the PR on any finding. +- **Nightly**: `.github/workflows/fuzz-nightly.yml` — 600s budget, on + failure uploads `fuzz/out/` as an artifact and opens (or comments on) + a `fuzz-nightly` issue assigned to `@jarvis9443`. diff --git a/fuzz/mutate_fuzz.py b/fuzz/mutate_fuzz.py new file mode 100644 index 0000000..9ae9a8d --- /dev/null +++ b/fuzz/mutate_fuzz.py @@ -0,0 +1,561 @@ +#!/usr/bin/env python3 +""" +Mutation fuzzer for lua-resty-openapi-validator. + +Takes a seed OpenAPI 3.x spec, applies N random AST-level mutations, then +generates positive request cases against each mutated spec and runs them +through the validator. Reports any crashes (validator threw a Lua error) +and any false negatives (a schema-conforming request was rejected). + +Mutations are deliberately biased toward the kinds of "weird but legal" +patterns that real-world specs use and that we've seen trigger validator +bugs: + + 1. Append a literal extension to a path-template segment + (`/users/{id}` -> `/users/{id}.json`) + 2. Add `nullable: true` (and sometimes `null` to enum/const) + 3. Add length keywords (`maxLength`, `minLength`) to non-string types + 4. Switch query param `style` between form/pipeDelimited/ + spaceDelimited and toggle `explode` + 5. Add `required` references to non-existent properties + 6. Swap scalar types (`integer` <-> `string` <-> `number` <-> `boolean`) + +Output: writes a JSON-lines findings report to fuzz/out/crashes.jsonl (both +crashes and false negatives). Exits non-zero if any finding was found. +""" +from __future__ import annotations + +import argparse +import copy +import json +import os +import random +import string +import subprocess +import sys +import time +from pathlib import Path +from typing import Any + +HERE = Path(__file__).resolve().parent +ROOT = HERE.parent + +# Mutation primitives --------------------------------------------------------- + +LITERAL_EXTS = [".json", ".xml", ".txt", ".v2"] +SCALAR_TYPES = ["string", "integer", "number", "boolean"] +ARRAY_STYLES = ["form", "pipeDelimited", "spaceDelimited"] + + +def _walk(node: Any, fn, path=()): + """In-order walk; calls fn(node, path) on every dict and list.""" + if isinstance(node, dict): + fn(node, path) + for k, v in list(node.items()): + _walk(v, fn, path + (k,)) + elif isinstance(node, list): + fn(node, path) + for i, v in enumerate(node): + _walk(v, fn, path + (i,)) + + +def m_path_extension(spec: dict, rng: random.Random) -> bool: + """Append a literal extension to one path that has a template param.""" + paths = list(spec.get("paths", {}).keys()) + cands = [p for p in paths if "{" in p and not any(p.endswith(e) for e in LITERAL_EXTS)] + if not cands: + return False + p = rng.choice(cands) + ext = rng.choice(LITERAL_EXTS) + spec["paths"][p + ext] = spec["paths"].pop(p) + return True + + +def m_nullable_enum(spec: dict, rng: random.Random) -> bool: + """Find a string enum somewhere and add nullable + null entry.""" + found = [] + + def visit(node, _path): + if isinstance(node, dict) and node.get("type") == "string" and isinstance(node.get("enum"), list): + found.append(node) + + _walk(spec, visit) + if not found: + return False + s = rng.choice(found) + s["nullable"] = True + if None not in s["enum"]: + s["enum"].append(None) + return True + + +def m_length_on_array(spec: dict, rng: random.Random) -> bool: + """Inject maxLength on an array-typed schema (a real-world miscoding).""" + found = [] + + def visit(node, _path): + if isinstance(node, dict) and node.get("type") == "array": + found.append(node) + + _walk(spec, visit) + if not found: + return False + s = rng.choice(found) + s["maxLength"] = rng.randint(1, 100) + return True + + +def m_param_style(spec: dict, rng: random.Random) -> bool: + """Switch a query-array param's style and explode.""" + found = [] + + def visit(node, _path): + if ( + isinstance(node, dict) + and node.get("in") == "query" + and isinstance(node.get("schema"), dict) + and node["schema"].get("type") == "array" + ): + found.append(node) + + _walk(spec, visit) + if not found: + return False + p = rng.choice(found) + p["style"] = rng.choice(ARRAY_STYLES) + p["explode"] = rng.choice([True, False]) + return True + + +def m_required_phantom(spec: dict, rng: random.Random) -> bool: + """Add a non-existent property name to required[].""" + found = [] + + def visit(node, _path): + if isinstance(node, dict) and isinstance(node.get("properties"), dict): + found.append(node) + + _walk(spec, visit) + if not found: + return False + s = rng.choice(found) + s.setdefault("required", []).append("__nonexistent_" + "".join(rng.choices(string.ascii_lowercase, k=4))) + return True + + +def m_swap_scalar_type(spec: dict, rng: random.Random) -> bool: + """Swap a leaf scalar type to another scalar.""" + found = [] + + def visit(node, _path): + if isinstance(node, dict) and node.get("type") in SCALAR_TYPES: + found.append(node) + + _walk(spec, visit) + if not found: + return False + s = rng.choice(found) + new_type = rng.choice([t for t in SCALAR_TYPES if t != s["type"]]) + s["type"] = new_type + # If swapping away from string, drop string-only keywords to keep schema realistic + if new_type != "string": + for k in ("minLength", "maxLength", "pattern", "format"): + s.pop(k, None) + return True + + +MUTATORS = [ + ("path_extension", m_path_extension), + ("nullable_enum", m_nullable_enum), + ("length_on_array", m_length_on_array), + ("param_style", m_param_style), + ("required_phantom", m_required_phantom), + ("swap_scalar_type", m_swap_scalar_type), +] + + +def mutate(spec: dict, n: int, rng: random.Random) -> list[str]: + """Apply up to n mutations; return list of applied mutator names.""" + applied = [] + for _ in range(n): + name, fn = rng.choice(MUTATORS) + if fn(spec, rng): + applied.append(name) + return applied + + +# $ref resolution --------------------------------------------------------------- + +def resolve_refs(spec: dict) -> dict: + """Recursively resolve all $ref pointers in the spec, returning a new tree.""" + def _resolve(node, root, seen_refs): + if isinstance(node, dict): + if "$ref" in node and isinstance(node["$ref"], str): + ref = node["$ref"] + if ref.startswith("#/"): + if ref in seen_refs: + return node + parts = ref[2:].split("/") + target = root + for p in parts: + p = p.replace("~1", "/").replace("~0", "~") + if isinstance(target, dict): + target = target.get(p) + else: + return node + if isinstance(target, dict): + resolved = copy.deepcopy(target) + return _resolve(resolved, root, seen_refs | {ref}) + return node + return {k: _resolve(v, root, seen_refs) for k, v in node.items()} + if isinstance(node, list): + return [_resolve(item, root, seen_refs) for item in node] + return node + return _resolve(spec, spec, set()) + + +# Case generation ------------------------------------------------------------- + +def _sample_string(rng: random.Random, schema: dict) -> str: + fmt = schema.get("format") + if fmt == "uuid": + return "00000000-0000-4000-8000-000000000000" + if fmt == "date": + return "2024-01-01" + if fmt == "date-time": + return "2024-01-01T00:00:00Z" + if fmt == "email": + return "x@y.z" + enum = schema.get("enum") + if isinstance(enum, list) and enum: + v = rng.choice(enum) + if v is not None: + return v + minl = schema.get("minLength", 1) + maxl = schema.get("maxLength", max(minl, 8)) + n = rng.randint(minl, max(minl, min(maxl, 16))) + return "x" * n + + +def sample_value(schema: dict, rng: random.Random, depth: int = 0): + """Generate a value that should validate against `schema`. Best-effort.""" + if not isinstance(schema, dict): + return None + if depth > 4: + return None + if schema.get("nullable") and rng.random() < 0.2: + return None + # Handle const/enum generically before type-specific branches + if "const" in schema: + return schema["const"] + enum = schema.get("enum") + if isinstance(enum, list) and enum: + return rng.choice(enum) + t = schema.get("type") + if isinstance(t, list): + t = rng.choice([x for x in t if x != "null"] or t) + if t == "string": + return _sample_string(rng, schema) + if t == "integer": + lo = schema.get("minimum", 0) + hi = schema.get("maximum", lo + 100) + try: + lo, hi = int(lo), int(hi) + except (TypeError, ValueError): + lo, hi = 0, 100 + if lo > hi: + lo, hi = hi, lo + return rng.randint(lo, hi) + if t == "number": + return float(rng.randint(0, 100)) + if t == "boolean": + return rng.choice([True, False]) + if t == "array": + items = schema.get("items", {}) + n = rng.randint(schema.get("minItems", 0), max(schema.get("minItems", 0), schema.get("maxItems", 3))) + return [sample_value(items, rng, depth + 1) for _ in range(n)] + if t == "object" or "properties" in schema: + props = schema.get("properties", {}) + required = set(schema.get("required", [])) + out = {} + for name, sub in props.items(): + if name in required or rng.random() < 0.4: + out[name] = sample_value(sub, rng, depth + 1) + return out + return None + + +def _merged_parameters(path_item: dict, op: dict) -> list[dict]: + """Merge path-item and operation-level parameters (op overrides).""" + merged = {} + for p in (path_item.get("parameters") or []) + (op.get("parameters") or []): + if isinstance(p, dict): + merged[(p.get("name"), p.get("in"))] = p + return list(merged.values()) + + +def gen_cases(spec: dict, rng: random.Random, max_per_op: int = 2) -> list[dict]: + """Generate a small set of positive requests per op (oracle: must accept).""" + cases = [] + for path, item in spec.get("paths", {}).items(): + if not isinstance(item, dict): + continue + op_count = 0 + for method, op in item.items(): + if method not in ("get", "post", "put", "delete", "patch", "head", "options"): + continue + if not isinstance(op, dict): + continue + if op_count >= max_per_op: + break + op_count += 1 + + params = _merged_parameters(item, op) + path_params = { + p["name"]: p + for p in params + if p.get("in") == "path" and isinstance(p.get("name"), str) + } + concrete = path + for token in (s.split("}", 1)[0] for s in path.split("{")[1:]): + pp = path_params.get(token, {}) + schema = pp.get("schema") or {"type": "string"} + v = sample_value(schema, rng) + if v is None: + v = "abc" + concrete = concrete.replace("{" + token + "}", str(v)) + + req = { + "method": method.upper(), + "path": concrete, + "query": {}, + "headers": {}, + } + + for p in params: + if not isinstance(p, dict): + continue + if not p.get("required"): + continue + schema = p.get("schema") or {"type": "string"} + val = sample_value(schema, rng) + if val is None: + val = "x" + if p.get("in") == "query": + if isinstance(val, list) and p.get("explode", True): + req["query"][p["name"]] = val + elif isinstance(val, list): + style = p.get("style", "form") + delim = { + "pipeDelimited": "|", + "spaceDelimited": " ", + }.get(style, ",") + req["query"][p["name"]] = delim.join(map(str, val)) + else: + req["query"][p["name"]] = val + elif p.get("in") == "header": + req["headers"][p["name"]] = str(val) + + # Body: generate matching JSON for application/json + rb = op.get("requestBody") + if isinstance(rb, dict): + content = rb.get("content", {}) + if "application/json" in content: + schema = content["application/json"].get("schema") or {} + val = sample_value(schema, rng) + req["content_type"] = "application/json" + req["body"] = json.dumps(val if val is not None else {}) + + cases.append({"label": "positive", "op": f"{method.upper()} {path}", "req": req}) + return cases + + +# Validator subprocess -------------------------------------------------------- + +RUNNER_LUA = r""" +-- Read JSON spec + JSONL cases on stdin: line 1 = spec, then one case per line. +local cjson = require("cjson.safe") +local ov = require("resty.openapi_validator") + +local function readline() + return io.read("*l") +end + +local spec_str = readline() +if not spec_str then return end +local v, cerr = ov.compile(spec_str) +if not v then + io.write(cjson.encode({phase="compile", error=tostring(cerr)}), "\n") + return +end + +while true do + local line = readline() + if not line then break end + local case = cjson.decode(line) + if not case then break end + local req = case.req + local pcall_ok, ok, err = pcall(v.validate_request, v, req) + if not pcall_ok then + io.write(cjson.encode({phase="crash", op=case.op, label=case.label, + err=tostring(ok), req=req}), "\n") + else + io.write(cjson.encode({phase="ok", op=case.op, label=case.label, + accepted=(ok==true), err=err and tostring(err) or nil}), "\n") + end +end +""" + + +def run_validator(spec: dict, cases: list[dict], deps: str, lib: str, + extra_includes: list[str] = None, timeout: float = 30.0): + payload = json.dumps(spec) + "\n" + "\n".join(json.dumps(c) for c in cases) + "\n" + cmd = ["resty", "--shdict", "test 1m", "-I", lib] + for inc in (extra_includes or []): + cmd += ["-I", inc] + if deps: + cmd += ["-I", deps + "/share/lua/5.1"] + cmd += ["-e", RUNNER_LUA] + env = os.environ.copy() + if deps: + env["LUA_CPATH"] = f"{deps}/lib/lua/5.1/?.so;;" + try: + r = subprocess.run(cmd, input=payload, capture_output=True, text=True, + timeout=timeout, env=env) + except subprocess.TimeoutExpired: + return [{"phase": "timeout", "stderr": "validator subprocess timed out"}] + out = [] + bad_lines = 0 + for line in r.stdout.splitlines(): + try: + out.append(json.loads(line)) + except json.JSONDecodeError: + bad_lines += 1 + if bad_lines and not out: + out.append({"phase": "subprocess_error", "rc": r.returncode, + "stderr": f"malformed validator JSONL output ({bad_lines} lines)"}) + if r.returncode != 0 and not out: + out.append({"phase": "subprocess_error", "rc": r.returncode, + "stderr": r.stderr[-2000:]}) + return out + + +# Driver ---------------------------------------------------------------------- + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--seeds", default=str(HERE / "seeds"), + help="directory of seed JSON specs") + ap.add_argument("--out", default=str(HERE / "out"), + help="output directory") + ap.add_argument("--budget", type=float, default=60.0, + help="wall-clock seconds for the fuzz session") + ap.add_argument("--mutations", type=int, default=4, + help="mutations to apply per round") + ap.add_argument("--seed", type=int, default=None, + help="RNG seed (for reproducibility)") + ap.add_argument("--deps", default=os.environ.get("GATEWAY_DEPS", ""), + help="optional: gateway-style deps directory (used to " + "locate jsonschema/cjson when not on the system " + "package path)") + ap.add_argument("--lib", default=str(ROOT / "lib"), + help="validator library path") + ap.add_argument("-I", "--include", action="append", default=[], + help="extra Lua include path (passed to resty -I)") + args = ap.parse_args() + + out = Path(args.out) + out.mkdir(parents=True, exist_ok=True) + crashes_path = out / "crashes.jsonl" + summary_path = out / "summary.json" + + rng_seed = args.seed if args.seed is not None else random.randint(0, 2**32 - 1) + rng = random.Random(rng_seed) + print(f"RNG seed: {rng_seed}", file=sys.stderr) + seeds = sorted(Path(args.seeds).glob("*.json")) + if not seeds: + print(f"no seeds found in {args.seeds}", file=sys.stderr) + sys.exit(2) + + crashes = [] + false_negatives = [] + rounds = 0 + cases_run = 0 + t0 = time.time() + + try: + with crashes_path.open("w") as crashf: + while time.time() - t0 < args.budget: + seed_path = rng.choice(seeds) + spec = json.loads(seed_path.read_text()) + spec.pop("servers", None) + applied = mutate(spec, args.mutations, rng) + resolved = resolve_refs(spec) + cases = gen_cases(resolved, rng, max_per_op=2) + if not cases: + continue + results = run_validator(spec, cases, args.deps, args.lib, args.include) + cases_run += len(cases) + rounds += 1 + for r in results: + phase = r.get("phase") + if phase in ("crash", "subprocess_error", "timeout"): + rec = {"kind": "crash", "seed": seed_path.name, "applied": applied, + "result": r} + crashes.append(rec) + crashf.write(json.dumps(rec) + "\n") + crashf.flush() + print(f"CRASH on {seed_path.name} after {applied}: " + f"{str(r.get('err') or r.get('stderr'))[:200]}", + file=sys.stderr) + elif phase == "ok" and r.get("label") == "positive" and not r.get("accepted"): + err = (r.get("err") or "").lower() + noisy = any(s in err for s in ( + "matches none of the required", + "match only one schema", + "discriminator", + "failed to match pattern", + "string too short, expected at least", + "string too long", + "expected at most", + "expected at least", + "additionalproperties", + "minimum", + "maximum", + "uniqueitems", + "format", + "got userdata", + "expected integer, got", + "expected number, got", + "expected boolean, got", + "is required", + "failed to validate item", + )) + if noisy: + continue + rec = {"kind": "false_negative", "seed": seed_path.name, + "applied": applied, "result": r} + false_negatives.append(rec) + crashf.write(json.dumps(rec) + "\n") + crashf.flush() + print(f"FALSE_NEGATIVE on {seed_path.name} after {applied}: " + f"op={r.get('op')} err={(r.get('err') or '')[:200]}", + file=sys.stderr) + finally: + summary = { + "rng_seed": rng_seed, + "rounds": rounds, + "cases_run": cases_run, + "elapsed_s": round(time.time() - t0, 2), + "crash_count": len(crashes), + "false_negative_count": len(false_negatives), + "total_findings": len(crashes) + len(false_negatives), + "crashes_path": str(crashes_path), + } + summary_path.write_text(json.dumps(summary, indent=2)) + print(json.dumps(summary, indent=2)) + sys.exit(1 if (crashes or false_negatives) else 0) + + +if __name__ == "__main__": + main() diff --git a/fuzz/seeds/discourse.json b/fuzz/seeds/discourse.json new file mode 100644 index 0000000..b60558b --- /dev/null +++ b/fuzz/seeds/discourse.json @@ -0,0 +1,19274 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Discourse API Documentation", + "x-logo": { + "url": "https://docs.discourse.org/logo.svg" + }, + "version": "latest", + "description": "This page contains the documentation on how to use Discourse through API calls.\n\n> Note: For any endpoints not listed you can follow the\n[reverse engineer the Discourse API](https://meta.discourse.org/t/-/20576)\nguide to figure out how to use an API endpoint.\n\n### Request Content-Type\n\nThe Content-Type for POST and PUT requests can be set to `application/x-www-form-urlencoded`,\n`multipart/form-data`, or `application/json`.\n\n### Endpoint Names and Response Content-Type\n\nMost API endpoints provide the same content as their HTML counterparts. For example\nthe URL `/categories` serves a list of categories, the `/categories.json` API provides the\nsame information in JSON format.\n\nInstead of sending API requests to `/categories.json` you may also send them to `/categories`\nand add an `Accept: application/json` header to the request to get the JSON response.\nSending requests with the `Accept` header is necessary if you want to use URLs\nfor related endpoints returned by the API, such as pagination URLs.\nThese URLs are returned without the `.json` prefix so you need to add the header in\norder to get the correct response format.\n\n### Authentication\n\nSome endpoints do not require any authentication, pretty much anything else will\nrequire you to be authenticated.\n\nTo become authenticated you will need to create an API Key from the admin panel.\n\nOnce you have your API Key you can pass it in along with your API Username\nas an HTTP header like this:\n\n```\ncurl -X GET \"http://127.0.0.1:3000/admin/users/list/active.json\" \\\n-H \"Api-Key: \" \\\n-H \"Api-Username: system\"\n```\n\nand this is how POST requests will look:\n\n```\ncurl -X POST \"http://127.0.0.1:3000/categories\" \\\n-H \"Content-Type: multipart/form-data;\" \\\n-H \"Api-Key: \" \\\n-H \"Api-Username: system\" \\\n-F \"name=89853c20-4409-e91a-a8ea-f6cdff96aaaa\" \\\n-F \"color=49d9e9\" \\\n-F \"text_color=f0fcfd\"\n```\n\n### Boolean values\n\nIf an endpoint accepts a boolean be sure to specify it as a lowercase\n`true` or `false` value unless noted otherwise.\n", + "license": { + "name": "MIT", + "url": "https://docs.discourse.org/LICENSE.txt" + } + }, + "paths": { + "/discourse-post-event/events.json": { + "get": { + "summary": "List calendar events", + "tags": [ + "Discourse Calendar - Events" + ], + "operationId": "listEvents", + "parameters": [ + { + "name": "include_details", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "description": "Include detailed event information (creator, invitees, stats,\netc.)" + }, + { + "name": "category_id", + "in": "query", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Filter events by category ID" + }, + { + "name": "include_subcategories", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "description": "Include events from subcategories when filtering by category" + }, + { + "name": "post_id", + "in": "query", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Filter to events associated with a specific post ID" + }, + { + "name": "attending_user", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "Filter to events where the specified user (username) has RSVP'd\nas going" + }, + { + "name": "before", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + }, + "description": "Return events starting before this date/time (ISO 8601 format)" + }, + { + "name": "after", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + }, + "description": "Return events starting after this date/time (ISO 8601 format)" + }, + { + "name": "order", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + }, + "description": "Sort order for events by start date (default: asc)" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 200 + }, + "description": "Maximum number of events to return (default: 200)" + } + ], + "responses": { + "200": { + "description": "success response (detailed)", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "events": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "category_id": { + "type": [ + "integer", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "recurrence": { + "type": [ + "string", + "null" + ] + }, + "recurrence_until": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "starts_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "ends_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "rrule": { + "type": "string" + }, + "show_local_time": { + "type": "boolean" + }, + "timezone": { + "type": [ + "string", + "null" + ] + }, + "duration": { + "type": "string", + "pattern": "^\\d{2}:\\d{2}:\\d{2}$" + }, + "all_day": { + "type": "boolean" + }, + "post": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "post_number": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "category_slug": { + "type": "string" + }, + "topic": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "tags_descriptions": { + "type": "object" + } + }, + "required": [ + "id", + "title", + "tags", + "tags_descriptions" + ] + } + }, + "required": [ + "id", + "post_number", + "url", + "category_slug", + "topic" + ] + }, + "occurrences": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "starts_at": { + "type": [ + "string", + "null" + ] + }, + "ends_at": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "starts_at", + "ends_at" + ] + } + }, + "can_act_on_discourse_post_event": { + "type": [ + "boolean", + "null" + ] + }, + "can_update_attendance": { + "type": [ + "boolean", + "null" + ] + }, + "creator": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "avatar_template" + ] + }, + "custom_fields": { + "type": [ + "object", + "null" + ] + }, + "is_closed": { + "type": "boolean" + }, + "is_expired": { + "type": "boolean" + }, + "is_ongoing": { + "type": "boolean" + }, + "is_private": { + "type": "boolean" + }, + "is_public": { + "type": "boolean" + }, + "is_standalone": { + "type": "boolean" + }, + "minimal": { + "type": [ + "boolean", + "null" + ] + }, + "raw_invitees": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "reminders": { + "type": "array", + "items": { + "type": "object", + "properties": { + "value": { + "type": "integer" + }, + "unit": { + "type": "string" + }, + "period": { + "type": "string", + "enum": [ + "before", + "after" + ] + }, + "type": { + "type": "string" + } + }, + "required": [ + "value", + "unit", + "period", + "type" + ] + } + }, + "sample_invitees": { + "type": "array", + "items": { + "type": "object" + } + }, + "should_display_invitees": { + "type": "boolean" + }, + "stats": { + "type": "object" + }, + "status": { + "type": "string", + "enum": [ + "public", + "private", + "standalone" + ] + }, + "url": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "description_html": { + "type": [ + "string", + "null" + ] + }, + "location": { + "type": [ + "string", + "null" + ] + }, + "watching_invitee": { + "type": [ + "object", + "null" + ] + }, + "chat_enabled": { + "type": [ + "boolean", + "null" + ] + }, + "channel": { + "type": "object" + }, + "max_attendees": { + "type": [ + "integer", + "null" + ] + }, + "at_capacity": { + "type": "boolean" + }, + "image_upload": { + "type": [ + "object", + "null" + ] + } + }, + "required": [ + "id", + "category_id", + "starts_at", + "ends_at", + "show_local_time", + "timezone", + "can_act_on_discourse_post_event", + "can_update_attendance", + "is_closed", + "is_expired", + "is_ongoing", + "is_private", + "is_public", + "is_standalone", + "should_display_invitees", + "status", + "at_capacity", + "post", + "occurrences" + ] + } + } + }, + "required": [ + "events" + ] + } + } + } + } + } + } + }, + "/discourse-post-event/events.ics": { + "get": { + "summary": "Export calendar events in iCalendar format", + "tags": [ + "Discourse Calendar - Events" + ], + "operationId": "exportEventsICS", + "parameters": [ + { + "name": "category_id", + "in": "query", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Filter events by category ID" + }, + { + "name": "include_subcategories", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "description": "Include events from subcategories when filtering by category" + }, + { + "name": "attending_user", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "Filter to events where the specified user (username) has RSVP'd\nas going" + }, + { + "name": "before", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + }, + "description": "Return events starting before this date/time (ISO 8601 format)" + }, + { + "name": "after", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + }, + "description": "Return events starting after this date/time (ISO 8601 format)" + }, + { + "name": "order", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + }, + "description": "Sort order for events by start date (default: asc)" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 200 + }, + "description": "Maximum number of events to return (default: 200)" + } + ], + "responses": { + "200": { + "description": "iCalendar file", + "content": { + "text/calendar": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + }, + "/admin/backups.json": { + "get": { + "summary": "List backups", + "tags": [ + "Backups" + ], + "operationId": "getBackups", + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "object", + "properties": { + "filename": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "last_modified": { + "type": "string" + } + }, + "required": [ + "filename", + "size", + "last_modified" + ] + } + } + } + } + } + } + }, + "post": { + "summary": "Create backup", + "tags": [ + "Backups" + ], + "operationId": "createBackup", + "parameters": [], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string", + "example": "OK" + } + }, + "required": [ + "success" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "with_uploads": { + "type": "boolean" + } + }, + "required": [ + "with_uploads" + ] + } + } + } + } + } + }, + "/admin/backups/{filename}": { + "put": { + "summary": "Send download backup email", + "tags": [ + "Backups" + ], + "operationId": "sendDownloadBackupEmail", + "parameters": [ + { + "name": "filename", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "success response" + } + } + }, + "get": { + "summary": "Download backup", + "tags": [ + "Backups" + ], + "operationId": "downloadBackup", + "parameters": [ + { + "name": "filename", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "token", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "success response" + } + } + } + }, + "/admin/badges.json": { + "get": { + "summary": "List badges", + "tags": [ + "Badges" + ], + "operationId": "adminListBadges", + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "badges": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "grant_count": { + "type": "integer" + }, + "allow_title": { + "type": "boolean" + }, + "multiple_grant": { + "type": "boolean" + }, + "icon": { + "type": "string" + }, + "image_url": { + "type": [ + "string", + "null" + ] + }, + "listable": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "badge_grouping_id": { + "type": "integer" + }, + "system": { + "type": "boolean" + }, + "long_description": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "manually_grantable": { + "type": "boolean" + }, + "query": { + "type": [ + "string", + "null" + ] + }, + "trigger": { + "type": [ + "integer", + "null" + ] + }, + "target_posts": { + "type": "boolean" + }, + "auto_revoke": { + "type": "boolean" + }, + "show_posts": { + "type": "boolean" + }, + "i18n_name": { + "type": [ + "string", + "null" + ] + }, + "image_upload_id": { + "type": [ + "integer", + "null" + ] + }, + "badge_type_id": { + "type": "integer" + }, + "show_in_post_header": { + "type": "boolean" + } + }, + "required": [ + "id", + "name", + "description", + "grant_count", + "allow_title", + "multiple_grant", + "icon", + "image_url", + "listable", + "enabled", + "badge_grouping_id", + "system", + "long_description", + "slug", + "manually_grantable", + "query", + "trigger", + "target_posts", + "auto_revoke", + "show_posts", + "badge_type_id", + "image_upload_id", + "show_in_post_header" + ] + } + }, + "badge_types": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "sort_order": { + "type": "integer" + } + }, + "required": [ + "id", + "name", + "sort_order" + ] + } + }, + "badge_groupings": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "position": { + "type": "integer" + }, + "system": { + "type": "boolean" + } + }, + "required": [ + "id", + "name", + "description", + "position", + "system" + ] + } + }, + "admin_badges": { + "type": "object", + "additionalProperties": false, + "properties": { + "protected_system_fields": { + "type": "array", + "items": {} + }, + "triggers": { + "type": "object", + "additionalProperties": false, + "properties": { + "user_change": { + "type": "integer" + }, + "none": { + "type": "integer" + }, + "post_revision": { + "type": "integer" + }, + "trust_level_change": { + "type": "integer" + }, + "post_action": { + "type": "integer" + } + }, + "required": [ + "user_change", + "none", + "post_revision", + "trust_level_change", + "post_action" + ] + }, + "badge_ids": { + "type": "array", + "items": {} + }, + "badge_grouping_ids": { + "type": "array", + "items": {} + }, + "badge_type_ids": { + "type": "array", + "items": {} + } + }, + "required": [ + "protected_system_fields", + "triggers", + "badge_ids", + "badge_grouping_ids", + "badge_type_ids" + ] + } + }, + "required": [ + "badges", + "badge_types", + "badge_groupings", + "admin_badges" + ] + } + } + } + } + } + }, + "post": { + "summary": "Create badge", + "tags": [ + "Badges" + ], + "operationId": "createBadge", + "parameters": [], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "badge_types": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "sort_order": { + "type": "integer" + } + }, + "required": [ + "id", + "name", + "sort_order" + ] + } + }, + "badge": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "grant_count": { + "type": "integer" + }, + "allow_title": { + "type": "boolean" + }, + "multiple_grant": { + "type": "boolean" + }, + "icon": { + "type": "string" + }, + "image_url": { + "type": [ + "string", + "null" + ] + }, + "image_upload_id": { + "type": [ + "integer", + "null" + ] + }, + "listable": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "badge_grouping_id": { + "type": "integer" + }, + "system": { + "type": "boolean" + }, + "long_description": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "manually_grantable": { + "type": "boolean" + }, + "query": { + "type": [ + "string", + "null" + ] + }, + "trigger": { + "type": [ + "string", + "null" + ] + }, + "target_posts": { + "type": "boolean" + }, + "auto_revoke": { + "type": "boolean" + }, + "show_posts": { + "type": "boolean" + }, + "badge_type_id": { + "type": "integer" + }, + "show_in_post_header": { + "type": "boolean" + } + }, + "required": [ + "id", + "name", + "description", + "grant_count", + "allow_title", + "multiple_grant", + "icon", + "image_url", + "listable", + "enabled", + "badge_grouping_id", + "system", + "long_description", + "slug", + "manually_grantable", + "query", + "trigger", + "target_posts", + "auto_revoke", + "show_posts", + "badge_type_id", + "image_upload_id", + "show_in_post_header" + ] + } + }, + "required": [ + "badge_types", + "badge" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "The name for the new badge." + }, + "badge_type_id": { + "type": "integer", + "description": "The ID for the badge type. 1 for Gold, 2 for Silver,\n3 for Bronze." + } + }, + "required": [ + "name", + "badge_type_id" + ] + } + } + } + } + } + }, + "/admin/badges/{id}.json": { + "put": { + "summary": "Update badge", + "tags": [ + "Badges" + ], + "operationId": "updateBadge", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "integer" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "badge_types": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "sort_order": { + "type": "integer" + } + }, + "required": [ + "id", + "name", + "sort_order" + ] + } + }, + "badge": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "grant_count": { + "type": "integer" + }, + "allow_title": { + "type": "boolean" + }, + "multiple_grant": { + "type": "boolean" + }, + "icon": { + "type": "string" + }, + "image_url": { + "type": [ + "string", + "null" + ] + }, + "image_upload_id": { + "type": [ + "integer", + "null" + ] + }, + "listable": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "badge_grouping_id": { + "type": "integer" + }, + "system": { + "type": "boolean" + }, + "long_description": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "manually_grantable": { + "type": "boolean" + }, + "query": { + "type": [ + "string", + "null" + ] + }, + "trigger": { + "type": [ + "string", + "null" + ] + }, + "target_posts": { + "type": "boolean" + }, + "auto_revoke": { + "type": "boolean" + }, + "show_posts": { + "type": "boolean" + }, + "badge_type_id": { + "type": "integer" + }, + "show_in_post_header": { + "type": "boolean" + } + }, + "required": [ + "id", + "name", + "description", + "grant_count", + "allow_title", + "multiple_grant", + "icon", + "image_url", + "listable", + "enabled", + "badge_grouping_id", + "system", + "long_description", + "slug", + "manually_grantable", + "query", + "trigger", + "target_posts", + "auto_revoke", + "show_posts", + "badge_type_id", + "image_upload_id", + "show_in_post_header" + ] + } + }, + "required": [ + "badge_types", + "badge" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "The name for the new badge." + }, + "badge_type_id": { + "type": "integer", + "description": "The ID for the badge type. 1 for Gold, 2 for Silver,\n3 for Bronze." + } + }, + "required": [ + "name", + "badge_type_id" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete badge", + "tags": [ + "Badges" + ], + "operationId": "deleteBadge", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "integer" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "success response" + } + } + } + }, + "/categories.json": { + "post": { + "summary": "Creates a category", + "tags": [ + "Categories" + ], + "operationId": "createCategory", + "parameters": [], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "category": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "color": { + "type": "string" + }, + "text_color": { + "type": "string" + }, + "style_type": { + "type": "string" + }, + "emoji": { + "type": [ + "string", + "null" + ] + }, + "icon": { + "type": [ + "string", + "null" + ] + }, + "slug": { + "type": "string" + }, + "locale": { + "type": [ + "string", + "null" + ] + }, + "topic_count": { + "type": "integer" + }, + "post_count": { + "type": "integer" + }, + "position": { + "type": "integer" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "description_text": { + "type": [ + "string", + "null" + ] + }, + "description_excerpt": { + "type": [ + "string", + "null" + ] + }, + "topic_url": { + "type": [ + "string", + "null" + ] + }, + "read_restricted": { + "type": "boolean" + }, + "permission": { + "type": [ + "integer", + "null" + ] + }, + "notification_level": { + "type": "integer" + }, + "can_edit": { + "type": "boolean" + }, + "topic_template": { + "type": [ + "string", + "null" + ] + }, + "topic_title_placeholder": { + "type": [ + "string", + "null" + ] + }, + "form_template_ids": { + "type": "array", + "items": {} + }, + "has_children": { + "type": [ + "boolean", + "null" + ] + }, + "subcategory_count": { + "type": [ + "integer", + "null" + ] + }, + "sort_order": { + "type": [ + "string", + "null" + ] + }, + "sort_ascending": { + "type": [ + "string", + "null" + ] + }, + "show_subcategory_list": { + "type": "boolean" + }, + "num_featured_topics": { + "type": "integer" + }, + "default_view": { + "type": [ + "string", + "null" + ] + }, + "subcategory_list_style": { + "type": "string" + }, + "default_top_period": { + "type": "string" + }, + "default_list_filter": { + "type": "string" + }, + "minimum_required_tags": { + "type": "integer" + }, + "navigate_to_first_post_after_read": { + "type": "boolean" + }, + "custom_fields": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "allowed_tags": { + "type": "array", + "items": {} + }, + "allowed_tag_groups": { + "type": "array", + "items": {} + }, + "allow_global_tags": { + "type": "boolean" + }, + "required_tag_groups": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "min_count": { + "type": "integer" + } + }, + "required": [ + "name", + "min_count" + ] + } + }, + "category_setting": { + "type": "object", + "additionalProperties": false, + "properties": { + "auto_bump_cooldown_days": { + "type": "integer" + }, + "num_auto_bump_daily": { + "type": [ + "integer", + "null" + ] + }, + "require_reply_approval": { + "type": [ + "boolean", + "null" + ] + }, + "require_topic_approval": { + "type": [ + "boolean", + "null" + ] + }, + "nested_replies_default": { + "type": [ + "boolean", + "null" + ] + }, + "topic_posting_review_mode": { + "type": "string" + }, + "reply_posting_review_mode": { + "type": "string" + } + } + }, + "category_localizations": { + "type": "array", + "items": {} + }, + "read_only_banner": { + "type": [ + "string", + "null" + ] + }, + "available_groups": { + "type": "array", + "items": {} + }, + "auto_close_hours": { + "type": [ + "string", + "null" + ] + }, + "auto_close_based_on_last_post": { + "type": "boolean" + }, + "allow_unlimited_owner_edits_on_first_post": { + "type": "boolean" + }, + "default_slow_mode_seconds": { + "type": [ + "string", + "null" + ] + }, + "group_permissions": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "permission_type": { + "type": "integer" + }, + "group_name": { + "type": "string" + }, + "group_id": { + "type": "integer" + } + }, + "required": [ + "permission_type", + "group_name", + "group_id" + ] + } + }, + "email_in": { + "type": [ + "string", + "null" + ] + }, + "email_in_allow_strangers": { + "type": "boolean" + }, + "mailinglist_mirror": { + "type": "boolean" + }, + "all_topics_wiki": { + "type": "boolean" + }, + "can_delete": { + "type": "boolean" + }, + "allow_badges": { + "type": "boolean" + }, + "topic_featured_link_allowed": { + "type": "boolean" + }, + "search_priority": { + "type": "integer" + }, + "topic_posting_review_group_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "reply_posting_review_group_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "uploaded_logo": { + "type": [ + "string", + "null" + ] + }, + "uploaded_logo_dark": { + "type": [ + "string", + "null" + ] + }, + "uploaded_background": { + "type": [ + "string", + "null" + ] + }, + "uploaded_background_dark": { + "type": [ + "string", + "null" + ] + }, + "category_types": { + "type": "object" + } + }, + "required": [ + "id", + "name", + "color", + "text_color", + "style_type", + "emoji", + "icon", + "slug", + "topic_count", + "post_count", + "position", + "description", + "description_text", + "description_excerpt", + "topic_url", + "read_restricted", + "permission", + "notification_level", + "can_edit", + "topic_template", + "topic_title_placeholder", + "has_children", + "subcategory_count", + "sort_order", + "sort_ascending", + "show_subcategory_list", + "num_featured_topics", + "default_view", + "subcategory_list_style", + "default_top_period", + "default_list_filter", + "minimum_required_tags", + "navigate_to_first_post_after_read", + "custom_fields", + "required_tag_groups", + "read_only_banner", + "available_groups", + "auto_close_hours", + "auto_close_based_on_last_post", + "allow_unlimited_owner_edits_on_first_post", + "default_slow_mode_seconds", + "group_permissions", + "email_in", + "email_in_allow_strangers", + "mailinglist_mirror", + "all_topics_wiki", + "can_delete", + "allow_badges", + "topic_featured_link_allowed", + "search_priority", + "topic_posting_review_group_ids", + "reply_posting_review_group_ids", + "uploaded_logo", + "uploaded_logo_dark", + "uploaded_background", + "uploaded_background_dark" + ] + } + }, + "required": [ + "category" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "color": { + "type": "string", + "example": "49d9e9" + }, + "text_color": { + "type": "string", + "example": "f0fcfd" + }, + "style_type": { + "type": "string" + }, + "emoji": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "parent_category_id": { + "type": "integer" + }, + "allow_badges": { + "type": "boolean" + }, + "slug": { + "type": "string" + }, + "topic_featured_links_allowed": { + "type": "boolean" + }, + "permissions": { + "type": "object", + "additionalProperties": true, + "properties": { + "everyone": { + "type": "integer", + "example": 1 + }, + "staff": { + "type": "integer" + } + } + }, + "search_priority": { + "type": "integer" + }, + "form_template_ids": { + "type": "array", + "items": {} + }, + "category_localizations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier for an existing localization.\nMust be included otherwise the record will be deleted." + }, + "locale": { + "type": "string", + "description": "The locale for the localization, e.g., 'en',\n'zh_CN'. Locale should be in the list of SiteSetting.content_localization_supported_locales." + }, + "name": { + "type": "string", + "description": "The name of the category in the specified locale." + }, + "description": { + "type": "string", + "description": "The description excerpt of the category in the\nspecified locale." + } + }, + "required": [ + "locale", + "name" + ] + } + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "get": { + "summary": "Retrieves a list of categories", + "tags": [ + "Categories" + ], + "operationId": "listCategories", + "parameters": [ + { + "name": "include_subcategories", + "in": "query", + "schema": { + "type": "boolean", + "enum": [ + true + ] + } + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "category_list": { + "type": "object", + "additionalProperties": false, + "properties": { + "can_create_category": { + "type": "boolean" + }, + "can_create_topic": { + "type": "boolean" + }, + "categories": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "color": { + "type": "string" + }, + "text_color": { + "type": "string" + }, + "style_type": { + "type": "string" + }, + "emoji": { + "type": [ + "string", + "null" + ] + }, + "icon": { + "type": [ + "string", + "null" + ] + }, + "slug": { + "type": "string" + }, + "topic_count": { + "type": "integer" + }, + "post_count": { + "type": "integer" + }, + "position": { + "type": "integer" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "description_text": { + "type": [ + "string", + "null" + ] + }, + "description_excerpt": { + "type": [ + "string", + "null" + ] + }, + "topic_url": { + "type": [ + "string", + "null" + ] + }, + "read_restricted": { + "type": "boolean" + }, + "permission": { + "type": "integer" + }, + "notification_level": { + "type": "integer" + }, + "can_edit": { + "type": "boolean" + }, + "topic_template": { + "type": [ + "string", + "null" + ] + }, + "topic_title_placeholder": { + "type": [ + "string", + "null" + ] + }, + "has_children": { + "type": "boolean" + }, + "subcategory_count": { + "type": [ + "integer", + "null" + ] + }, + "sort_order": { + "type": [ + "string", + "null" + ] + }, + "sort_ascending": { + "type": [ + "string", + "null" + ] + }, + "show_subcategory_list": { + "type": "boolean" + }, + "num_featured_topics": { + "type": "integer" + }, + "default_view": { + "type": [ + "string", + "null" + ] + }, + "subcategory_list_style": { + "type": "string" + }, + "default_top_period": { + "type": "string" + }, + "default_list_filter": { + "type": "string" + }, + "minimum_required_tags": { + "type": "integer" + }, + "navigate_to_first_post_after_read": { + "type": "boolean" + }, + "topics_day": { + "type": "integer" + }, + "topics_week": { + "type": "integer" + }, + "topics_month": { + "type": "integer" + }, + "topics_year": { + "type": "integer" + }, + "topics_all_time": { + "type": "integer" + }, + "is_uncategorized": { + "type": "boolean" + }, + "subcategory_ids": { + "type": "array", + "items": {} + }, + "subcategory_list": { + "type": [ + "array", + "null" + ], + "items": {} + }, + "uploaded_logo": { + "type": [ + "string", + "null" + ] + }, + "uploaded_logo_dark": { + "type": [ + "string", + "null" + ] + }, + "uploaded_background": { + "type": [ + "string", + "null" + ] + }, + "uploaded_background_dark": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "name", + "color", + "text_color", + "style_type", + "emoji", + "icon", + "slug", + "topic_count", + "post_count", + "position", + "description", + "description_text", + "description_excerpt", + "topic_url", + "read_restricted", + "permission", + "notification_level", + "can_edit", + "topic_template", + "topic_title_placeholder", + "has_children", + "subcategory_count", + "sort_order", + "sort_ascending", + "show_subcategory_list", + "num_featured_topics", + "default_view", + "subcategory_list_style", + "default_top_period", + "default_list_filter", + "minimum_required_tags", + "navigate_to_first_post_after_read", + "topics_day", + "topics_week", + "topics_month", + "topics_year", + "topics_all_time", + "subcategory_ids", + "uploaded_logo", + "uploaded_logo_dark", + "uploaded_background", + "uploaded_background_dark" + ] + } + } + }, + "required": [ + "can_create_category", + "can_create_topic", + "categories" + ] + } + }, + "required": [ + "category_list" + ] + } + } + } + } + } + } + }, + "/categories/{id}.json": { + "put": { + "summary": "Updates a category", + "tags": [ + "Categories" + ], + "operationId": "updateCategory", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "integer" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string" + }, + "category": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "color": { + "type": "string" + }, + "text_color": { + "type": "string" + }, + "style_type": { + "type": "string" + }, + "emoji": { + "type": [ + "string", + "null" + ] + }, + "icon": { + "type": [ + "string", + "null" + ] + }, + "slug": { + "type": "string" + }, + "locale": { + "type": [ + "string", + "null" + ] + }, + "topic_count": { + "type": "integer" + }, + "post_count": { + "type": "integer" + }, + "position": { + "type": "integer" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "description_text": { + "type": [ + "string", + "null" + ] + }, + "description_excerpt": { + "type": [ + "string", + "null" + ] + }, + "topic_url": { + "type": [ + "string", + "null" + ] + }, + "read_restricted": { + "type": "boolean" + }, + "permission": { + "type": [ + "integer", + "null" + ] + }, + "notification_level": { + "type": "integer" + }, + "can_edit": { + "type": "boolean" + }, + "topic_template": { + "type": [ + "string", + "null" + ] + }, + "topic_title_placeholder": { + "type": [ + "string", + "null" + ] + }, + "form_template_ids": { + "type": "array", + "items": {} + }, + "has_children": { + "type": [ + "boolean", + "null" + ] + }, + "subcategory_count": { + "type": [ + "integer", + "null" + ] + }, + "sort_order": { + "type": [ + "string", + "null" + ] + }, + "sort_ascending": { + "type": [ + "string", + "null" + ] + }, + "show_subcategory_list": { + "type": "boolean" + }, + "num_featured_topics": { + "type": "integer" + }, + "default_view": { + "type": [ + "string", + "null" + ] + }, + "subcategory_list_style": { + "type": "string" + }, + "default_top_period": { + "type": "string" + }, + "default_list_filter": { + "type": "string" + }, + "minimum_required_tags": { + "type": "integer" + }, + "navigate_to_first_post_after_read": { + "type": "boolean" + }, + "custom_fields": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "allowed_tags": { + "type": "array", + "items": {} + }, + "allowed_tag_groups": { + "type": "array", + "items": {} + }, + "allow_global_tags": { + "type": "boolean" + }, + "required_tag_groups": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "min_count": { + "type": "integer" + } + }, + "required": [ + "name", + "min_count" + ] + } + }, + "category_setting": { + "type": "object", + "additionalProperties": false, + "properties": { + "auto_bump_cooldown_days": { + "type": "integer" + }, + "num_auto_bump_daily": { + "type": [ + "integer", + "null" + ] + }, + "require_reply_approval": { + "type": [ + "boolean", + "null" + ] + }, + "require_topic_approval": { + "type": [ + "boolean", + "null" + ] + }, + "nested_replies_default": { + "type": [ + "boolean", + "null" + ] + }, + "topic_posting_review_mode": { + "type": "string" + }, + "reply_posting_review_mode": { + "type": "string" + } + } + }, + "category_localizations": { + "type": "array", + "items": {} + }, + "read_only_banner": { + "type": [ + "string", + "null" + ] + }, + "available_groups": { + "type": "array", + "items": {} + }, + "auto_close_hours": { + "type": [ + "string", + "null" + ] + }, + "auto_close_based_on_last_post": { + "type": "boolean" + }, + "allow_unlimited_owner_edits_on_first_post": { + "type": "boolean" + }, + "default_slow_mode_seconds": { + "type": [ + "string", + "null" + ] + }, + "group_permissions": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "permission_type": { + "type": "integer" + }, + "group_name": { + "type": "string" + }, + "group_id": { + "type": "integer" + } + }, + "required": [ + "permission_type", + "group_name", + "group_id" + ] + } + }, + "email_in": { + "type": [ + "string", + "null" + ] + }, + "email_in_allow_strangers": { + "type": "boolean" + }, + "mailinglist_mirror": { + "type": "boolean" + }, + "all_topics_wiki": { + "type": "boolean" + }, + "can_delete": { + "type": "boolean" + }, + "allow_badges": { + "type": "boolean" + }, + "topic_featured_link_allowed": { + "type": "boolean" + }, + "search_priority": { + "type": "integer" + }, + "topic_posting_review_group_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "reply_posting_review_group_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "uploaded_logo": { + "type": [ + "string", + "null" + ] + }, + "uploaded_logo_dark": { + "type": [ + "string", + "null" + ] + }, + "uploaded_background": { + "type": [ + "string", + "null" + ] + }, + "uploaded_background_dark": { + "type": [ + "string", + "null" + ] + }, + "category_types": { + "type": "object" + } + }, + "required": [ + "id", + "name", + "color", + "text_color", + "slug", + "topic_count", + "post_count", + "position", + "description", + "description_text", + "description_excerpt", + "topic_url", + "read_restricted", + "permission", + "notification_level", + "can_edit", + "topic_template", + "topic_title_placeholder", + "form_template_ids", + "has_children", + "subcategory_count", + "sort_order", + "sort_ascending", + "show_subcategory_list", + "num_featured_topics", + "default_view", + "subcategory_list_style", + "default_top_period", + "default_list_filter", + "minimum_required_tags", + "navigate_to_first_post_after_read", + "custom_fields", + "required_tag_groups", + "read_only_banner", + "available_groups", + "auto_close_hours", + "auto_close_based_on_last_post", + "allow_unlimited_owner_edits_on_first_post", + "default_slow_mode_seconds", + "group_permissions", + "email_in", + "email_in_allow_strangers", + "mailinglist_mirror", + "all_topics_wiki", + "can_delete", + "allow_badges", + "topic_featured_link_allowed", + "search_priority", + "topic_posting_review_group_ids", + "reply_posting_review_group_ids", + "uploaded_logo", + "uploaded_logo_dark", + "uploaded_background", + "uploaded_background_dark" + ] + } + }, + "required": [ + "success", + "category" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "color": { + "type": "string", + "example": "49d9e9" + }, + "text_color": { + "type": "string", + "example": "f0fcfd" + }, + "style_type": { + "type": "string" + }, + "emoji": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "parent_category_id": { + "type": "integer" + }, + "allow_badges": { + "type": "boolean" + }, + "slug": { + "type": "string" + }, + "topic_featured_links_allowed": { + "type": "boolean" + }, + "permissions": { + "type": "object", + "additionalProperties": true, + "properties": { + "everyone": { + "type": "integer", + "example": 1 + }, + "staff": { + "type": "integer" + } + } + }, + "search_priority": { + "type": "integer" + }, + "form_template_ids": { + "type": "array", + "items": {} + }, + "category_localizations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier for an existing localization.\nMust be included otherwise the record will be deleted." + }, + "locale": { + "type": "string", + "description": "The locale for the localization, e.g., 'en',\n'zh_CN'. Locale should be in the list of SiteSetting.content_localization_supported_locales." + }, + "name": { + "type": "string", + "description": "The name of the category in the specified locale." + }, + "description": { + "type": "string", + "description": "The description excerpt of the category in the\nspecified locale." + } + }, + "required": [ + "locale", + "name" + ] + } + } + }, + "required": [ + "name" + ] + } + } + } + } + } + }, + "/c/{slug}/{id}.json": { + "get": { + "summary": "List topics", + "tags": [ + "Categories" + ], + "operationId": "listCategoryTopics", + "parameters": [ + { + "name": "slug", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "integer" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template" + ] + } + }, + "primary_groups": { + "type": "array", + "items": {} + }, + "topic_list": { + "type": "object", + "additionalProperties": false, + "properties": { + "can_create_topic": { + "type": "boolean" + }, + "per_page": { + "type": "integer" + }, + "top_tags": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "slug" + ] + } + }, + "topics": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "fancy_title": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "posts_count": { + "type": "integer" + }, + "reply_count": { + "type": "integer" + }, + "highest_post_number": { + "type": "integer" + }, + "image_url": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "last_posted_at": { + "type": "string" + }, + "bumped": { + "type": "boolean" + }, + "bumped_at": { + "type": "string" + }, + "archetype": { + "type": "string" + }, + "unseen": { + "type": "boolean" + }, + "pinned": { + "type": "boolean" + }, + "unpinned": { + "type": [ + "string", + "null" + ] + }, + "excerpt": { + "type": "string" + }, + "visible": { + "type": "boolean" + }, + "closed": { + "type": "boolean" + }, + "archived": { + "type": "boolean" + }, + "bookmarked": { + "type": [ + "string", + "null" + ] + }, + "liked": { + "type": [ + "string", + "null" + ] + }, + "views": { + "type": "integer" + }, + "like_count": { + "type": "integer" + }, + "has_summary": { + "type": "boolean" + }, + "last_poster_username": { + "type": "string" + }, + "category_id": { + "type": "integer" + }, + "pinned_globally": { + "type": "boolean" + }, + "featured_link": { + "type": [ + "string", + "null" + ] + }, + "posters": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "extras": { + "type": "string" + }, + "description": { + "type": "string" + }, + "user_id": { + "type": "integer" + }, + "primary_group_id": { + "type": [ + "integer", + "null" + ] + } + }, + "required": [ + "extras", + "description", + "user_id", + "primary_group_id" + ] + } + } + }, + "required": [ + "id", + "title", + "fancy_title", + "slug", + "posts_count", + "reply_count", + "highest_post_number", + "image_url", + "created_at", + "last_posted_at", + "bumped", + "bumped_at", + "archetype", + "unseen", + "pinned", + "unpinned", + "excerpt", + "visible", + "closed", + "archived", + "bookmarked", + "liked", + "views", + "like_count", + "has_summary", + "last_poster_username", + "category_id", + "pinned_globally", + "featured_link", + "posters" + ] + } + } + }, + "required": [ + "can_create_topic", + "per_page", + "topics" + ] + } + }, + "required": [ + "topic_list" + ] + } + } + } + } + } + } + }, + "/c/{id}/show.json": { + "get": { + "summary": "Show category", + "tags": [ + "Categories" + ], + "operationId": "getCategory", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "integer" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "category": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "color": { + "type": "string" + }, + "text_color": { + "type": "string" + }, + "style_type": { + "type": "string" + }, + "emoji": { + "type": [ + "string", + "null" + ] + }, + "icon": { + "type": [ + "string", + "null" + ] + }, + "slug": { + "type": "string" + }, + "locale": { + "type": [ + "string", + "null" + ] + }, + "topic_count": { + "type": "integer" + }, + "post_count": { + "type": "integer" + }, + "position": { + "type": "integer" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "description_text": { + "type": [ + "string", + "null" + ] + }, + "description_excerpt": { + "type": [ + "string", + "null" + ] + }, + "topic_url": { + "type": [ + "string", + "null" + ] + }, + "read_restricted": { + "type": "boolean" + }, + "permission": { + "type": [ + "integer", + "null" + ] + }, + "notification_level": { + "type": "integer" + }, + "can_edit": { + "type": "boolean" + }, + "topic_template": { + "type": [ + "string", + "null" + ] + }, + "topic_title_placeholder": { + "type": [ + "string", + "null" + ] + }, + "form_template_ids": { + "type": "array", + "items": {} + }, + "has_children": { + "type": [ + "boolean", + "null" + ] + }, + "subcategory_count": { + "type": [ + "integer", + "null" + ] + }, + "sort_order": { + "type": [ + "string", + "null" + ] + }, + "sort_ascending": { + "type": [ + "string", + "null" + ] + }, + "show_subcategory_list": { + "type": "boolean" + }, + "num_featured_topics": { + "type": "integer" + }, + "default_view": { + "type": [ + "string", + "null" + ] + }, + "subcategory_list_style": { + "type": "string" + }, + "default_top_period": { + "type": "string" + }, + "default_list_filter": { + "type": "string" + }, + "minimum_required_tags": { + "type": "integer" + }, + "navigate_to_first_post_after_read": { + "type": "boolean" + }, + "custom_fields": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "allowed_tags": { + "type": "array", + "items": {} + }, + "allowed_tag_groups": { + "type": "array", + "items": {} + }, + "allow_global_tags": { + "type": "boolean" + }, + "required_tag_groups": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "min_count": { + "type": "integer" + } + }, + "required": [ + "name", + "min_count" + ] + } + }, + "category_setting": { + "type": "object", + "additionalProperties": false, + "properties": { + "auto_bump_cooldown_days": { + "type": "integer" + }, + "num_auto_bump_daily": { + "type": [ + "integer", + "null" + ] + }, + "require_reply_approval": { + "type": [ + "boolean", + "null" + ] + }, + "require_topic_approval": { + "type": [ + "boolean", + "null" + ] + }, + "nested_replies_default": { + "type": [ + "boolean", + "null" + ] + }, + "topic_posting_review_mode": { + "type": "string" + }, + "reply_posting_review_mode": { + "type": "string" + } + } + }, + "category_localizations": { + "type": "array", + "items": {} + }, + "read_only_banner": { + "type": [ + "string", + "null" + ] + }, + "available_groups": { + "type": "array", + "items": {} + }, + "auto_close_hours": { + "type": [ + "string", + "null" + ] + }, + "auto_close_based_on_last_post": { + "type": "boolean" + }, + "allow_unlimited_owner_edits_on_first_post": { + "type": "boolean" + }, + "default_slow_mode_seconds": { + "type": [ + "string", + "null" + ] + }, + "group_permissions": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "permission_type": { + "type": "integer" + }, + "group_name": { + "type": "string" + }, + "group_id": { + "type": "integer" + } + }, + "required": [ + "permission_type", + "group_name", + "group_id" + ] + } + }, + "email_in": { + "type": [ + "string", + "null" + ] + }, + "email_in_allow_strangers": { + "type": "boolean" + }, + "mailinglist_mirror": { + "type": "boolean" + }, + "all_topics_wiki": { + "type": "boolean" + }, + "can_delete": { + "type": "boolean" + }, + "allow_badges": { + "type": "boolean" + }, + "topic_featured_link_allowed": { + "type": "boolean" + }, + "search_priority": { + "type": "integer" + }, + "topic_posting_review_group_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "reply_posting_review_group_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "uploaded_logo": { + "type": [ + "string", + "null" + ] + }, + "uploaded_logo_dark": { + "type": [ + "string", + "null" + ] + }, + "uploaded_background": { + "type": [ + "string", + "null" + ] + }, + "uploaded_background_dark": { + "type": [ + "string", + "null" + ] + }, + "category_types": { + "type": "object" + } + }, + "required": [ + "id", + "name", + "color", + "text_color", + "style_type", + "emoji", + "icon", + "slug", + "topic_count", + "post_count", + "position", + "description", + "description_text", + "description_excerpt", + "topic_url", + "read_restricted", + "permission", + "notification_level", + "can_edit", + "topic_template", + "topic_title_placeholder", + "has_children", + "subcategory_count", + "sort_order", + "sort_ascending", + "show_subcategory_list", + "num_featured_topics", + "default_view", + "subcategory_list_style", + "default_top_period", + "default_list_filter", + "minimum_required_tags", + "navigate_to_first_post_after_read", + "custom_fields", + "required_tag_groups", + "read_only_banner", + "available_groups", + "auto_close_hours", + "auto_close_based_on_last_post", + "allow_unlimited_owner_edits_on_first_post", + "default_slow_mode_seconds", + "group_permissions", + "email_in", + "email_in_allow_strangers", + "mailinglist_mirror", + "all_topics_wiki", + "can_delete", + "allow_badges", + "topic_featured_link_allowed", + "search_priority", + "topic_posting_review_group_ids", + "reply_posting_review_group_ids", + "uploaded_logo", + "uploaded_logo_dark", + "uploaded_background", + "uploaded_background_dark" + ] + } + }, + "required": [ + "category" + ] + } + } + } + } + } + } + }, + "/admin/groups.json": { + "post": { + "summary": "Create a group", + "tags": [ + "Groups" + ], + "operationId": "createGroup", + "parameters": [], + "responses": { + "200": { + "description": "group created", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "basic_group": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "automatic": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "user_count": { + "type": "integer" + }, + "mentionable_level": { + "type": "integer" + }, + "messageable_level": { + "type": "integer" + }, + "visibility_level": { + "type": "integer" + }, + "primary_group": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "grant_trust_level": { + "type": [ + "string", + "null" + ] + }, + "incoming_email": { + "type": [ + "string", + "null" + ] + }, + "has_messages": { + "type": "boolean" + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "bio_raw": { + "type": [ + "string", + "null" + ] + }, + "bio_cooked": { + "type": [ + "string", + "null" + ] + }, + "bio_excerpt": { + "type": [ + "string", + "null" + ] + }, + "public_admission": { + "type": "boolean" + }, + "public_exit": { + "type": "boolean" + }, + "allow_membership_requests": { + "type": "boolean" + }, + "full_name": { + "type": [ + "string", + "null" + ] + }, + "default_notification_level": { + "type": "integer" + }, + "membership_request_template": { + "type": [ + "string", + "null" + ] + }, + "members_visibility_level": { + "type": "integer" + }, + "can_see_members": { + "type": "boolean" + }, + "can_admin_group": { + "type": "boolean" + }, + "can_edit_group": { + "type": "boolean" + }, + "publish_read_state": { + "type": "boolean" + } + }, + "required": [ + "id", + "automatic", + "name", + "user_count", + "mentionable_level", + "messageable_level", + "visibility_level", + "primary_group", + "title", + "grant_trust_level", + "incoming_email", + "has_messages", + "flair_url", + "flair_bg_color", + "flair_color", + "bio_raw", + "bio_cooked", + "bio_excerpt", + "public_admission", + "public_exit", + "allow_membership_requests", + "full_name", + "default_notification_level", + "membership_request_template", + "members_visibility_level", + "can_see_members", + "can_admin_group", + "publish_read_state" + ] + } + }, + "required": [ + "basic_group" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "group": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "bio_raw": { + "type": "string", + "description": "About Group" + }, + "usernames": { + "type": "string", + "description": "comma,separated" + }, + "owner_usernames": { + "type": "string", + "description": "comma,separated" + }, + "automatic_membership_email_domains": { + "type": "string", + "description": "pipe|separated" + }, + "visibility_level": { + "type": "integer" + }, + "primary_group": { + "type": "boolean" + }, + "flair_icon": { + "type": "string" + }, + "flair_upload_id": { + "type": "integer" + }, + "flair_bg_color": { + "type": "string" + }, + "public_admission": { + "type": "boolean" + }, + "public_exit": { + "type": "boolean" + }, + "default_notification_level": { + "type": "integer" + }, + "muted_category_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "regular_category_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "watching_category_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "tracking_category_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "watching_first_post_category_ids": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + "required": [ + "name" + ] + } + }, + "required": [ + "group" + ] + } + } + } + } + } + }, + "/admin/groups/{id}.json": { + "delete": { + "summary": "Delete a group", + "tags": [ + "Groups" + ], + "operationId": "deleteGroup", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string", + "example": "OK" + } + }, + "required": [ + "success" + ] + } + } + } + } + } + } + }, + "/groups/{name}.json": { + "get": { + "summary": "Get a group", + "tags": [ + "Groups" + ], + "operationId": "getGroup", + "parameters": [ + { + "name": "name", + "in": "path", + "example": "name", + "description": "Use group name instead of id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "group": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "automatic": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "user_count": { + "type": "integer" + }, + "mentionable_level": { + "type": "integer" + }, + "messageable_level": { + "type": "integer" + }, + "visibility_level": { + "type": "integer" + }, + "primary_group": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "grant_trust_level": { + "type": [ + "string", + "null" + ] + }, + "incoming_email": { + "type": [ + "string", + "null" + ] + }, + "has_messages": { + "type": "boolean" + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "bio_raw": { + "type": [ + "string", + "null" + ] + }, + "bio_cooked": { + "type": [ + "string", + "null" + ] + }, + "bio_excerpt": { + "type": [ + "string", + "null" + ] + }, + "public_admission": { + "type": "boolean" + }, + "public_exit": { + "type": "boolean" + }, + "allow_membership_requests": { + "type": "boolean" + }, + "full_name": { + "type": [ + "string", + "null" + ] + }, + "default_notification_level": { + "type": "integer" + }, + "membership_request_template": { + "type": [ + "string", + "null" + ] + }, + "is_group_user": { + "type": "boolean" + }, + "members_visibility_level": { + "type": "integer" + }, + "can_see_members": { + "type": "boolean" + }, + "can_admin_group": { + "type": "boolean" + }, + "can_edit_group": { + "type": "boolean" + }, + "publish_read_state": { + "type": "boolean" + }, + "is_group_owner_display": { + "type": "boolean" + }, + "mentionable": { + "type": "boolean" + }, + "messageable": { + "type": "boolean" + }, + "automatic_membership_email_domains": { + "type": [ + "string", + "null" + ] + }, + "smtp_updated_at": { + "type": [ + "string", + "null" + ] + }, + "smtp_updated_by": { + "type": [ + "object", + "null" + ] + }, + "smtp_enabled": { + "type": "boolean" + }, + "smtp_server": { + "type": [ + "string", + "null" + ] + }, + "smtp_port": { + "type": [ + "string", + "null" + ] + }, + "smtp_ssl_mode": { + "type": [ + "integer", + "null" + ] + }, + "email_username": { + "type": [ + "string", + "null" + ] + }, + "email_from_alias": { + "type": [ + "string", + "null" + ] + }, + "email_password": { + "type": [ + "string", + "null" + ] + }, + "message_count": { + "type": "integer" + }, + "allow_unknown_sender_topic_replies": { + "type": "boolean" + }, + "associated_group_ids": { + "type": "array", + "items": {} + }, + "watching_category_ids": { + "type": "array", + "items": {} + }, + "tracking_category_ids": { + "type": "array", + "items": {} + }, + "watching_first_post_category_ids": { + "type": "array", + "items": {} + }, + "regular_category_ids": { + "type": "array", + "items": {} + }, + "muted_category_ids": { + "type": "array", + "items": {} + }, + "watching_tags": { + "type": "array", + "items": {} + }, + "watching_first_post_tags": { + "type": "array", + "items": {} + }, + "tracking_tags": { + "type": "array", + "items": {} + }, + "regular_tags": { + "type": "array", + "items": {} + }, + "muted_tags": { + "type": "array", + "items": {} + } + }, + "required": [ + "id", + "automatic", + "name", + "user_count", + "mentionable_level", + "messageable_level", + "visibility_level", + "primary_group", + "title", + "grant_trust_level", + "incoming_email", + "has_messages", + "flair_url", + "flair_bg_color", + "flair_color", + "bio_raw", + "bio_cooked", + "bio_excerpt", + "public_admission", + "public_exit", + "allow_membership_requests", + "full_name", + "default_notification_level", + "membership_request_template", + "is_group_user", + "members_visibility_level", + "can_see_members", + "can_admin_group", + "publish_read_state", + "is_group_owner_display", + "mentionable", + "messageable", + "automatic_membership_email_domains", + "smtp_server", + "smtp_port", + "smtp_ssl_mode", + "email_username", + "email_password", + "message_count", + "allow_unknown_sender_topic_replies", + "watching_category_ids", + "tracking_category_ids", + "watching_first_post_category_ids", + "regular_category_ids", + "muted_category_ids" + ] + }, + "extras": { + "type": "object", + "additionalProperties": false, + "properties": { + "visible_group_names": { + "type": "array", + "items": {} + } + }, + "required": [ + "visible_group_names" + ] + } + }, + "required": [ + "group", + "extras" + ] + } + } + } + } + } + } + }, + "/groups/{id}.json": { + "put": { + "summary": "Update a group", + "tags": [ + "Groups" + ], + "operationId": "updateGroup", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string", + "example": "OK" + } + }, + "required": [ + "success" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "group": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "bio_raw": { + "type": "string", + "description": "About Group" + }, + "usernames": { + "type": "string", + "description": "comma,separated" + }, + "owner_usernames": { + "type": "string", + "description": "comma,separated" + }, + "automatic_membership_email_domains": { + "type": "string", + "description": "pipe|separated" + }, + "visibility_level": { + "type": "integer" + }, + "primary_group": { + "type": "boolean" + }, + "flair_icon": { + "type": "string" + }, + "flair_upload_id": { + "type": "integer" + }, + "flair_bg_color": { + "type": "string" + }, + "public_admission": { + "type": "boolean" + }, + "public_exit": { + "type": "boolean" + }, + "default_notification_level": { + "type": "integer" + }, + "muted_category_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "regular_category_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "watching_category_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "tracking_category_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "watching_first_post_category_ids": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + "required": [ + "name" + ] + } + }, + "required": [ + "group" + ] + } + } + } + } + } + }, + "/groups/by-id/{id}.json": { + "get": { + "summary": "Get a group by id", + "tags": [ + "Groups" + ], + "operationId": "getGroupById", + "parameters": [ + { + "name": "id", + "in": "path", + "example": "name", + "description": "Use group name instead of id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "success response (by id)", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "group": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "automatic": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "user_count": { + "type": "integer" + }, + "mentionable_level": { + "type": "integer" + }, + "messageable_level": { + "type": "integer" + }, + "visibility_level": { + "type": "integer" + }, + "primary_group": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "grant_trust_level": { + "type": [ + "string", + "null" + ] + }, + "incoming_email": { + "type": [ + "string", + "null" + ] + }, + "has_messages": { + "type": "boolean" + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "bio_raw": { + "type": [ + "string", + "null" + ] + }, + "bio_cooked": { + "type": [ + "string", + "null" + ] + }, + "bio_excerpt": { + "type": [ + "string", + "null" + ] + }, + "public_admission": { + "type": "boolean" + }, + "public_exit": { + "type": "boolean" + }, + "allow_membership_requests": { + "type": "boolean" + }, + "full_name": { + "type": [ + "string", + "null" + ] + }, + "default_notification_level": { + "type": "integer" + }, + "membership_request_template": { + "type": [ + "string", + "null" + ] + }, + "is_group_user": { + "type": "boolean" + }, + "members_visibility_level": { + "type": "integer" + }, + "can_see_members": { + "type": "boolean" + }, + "can_admin_group": { + "type": "boolean" + }, + "can_edit_group": { + "type": "boolean" + }, + "publish_read_state": { + "type": "boolean" + }, + "is_group_owner_display": { + "type": "boolean" + }, + "mentionable": { + "type": "boolean" + }, + "messageable": { + "type": "boolean" + }, + "automatic_membership_email_domains": { + "type": [ + "string", + "null" + ] + }, + "smtp_updated_at": { + "type": [ + "string", + "null" + ] + }, + "smtp_updated_by": { + "type": [ + "object", + "null" + ] + }, + "smtp_enabled": { + "type": "boolean" + }, + "smtp_server": { + "type": [ + "string", + "null" + ] + }, + "smtp_port": { + "type": [ + "string", + "null" + ] + }, + "smtp_ssl_mode": { + "type": [ + "integer", + "null" + ] + }, + "email_username": { + "type": [ + "string", + "null" + ] + }, + "email_from_alias": { + "type": [ + "string", + "null" + ] + }, + "email_password": { + "type": [ + "string", + "null" + ] + }, + "message_count": { + "type": "integer" + }, + "allow_unknown_sender_topic_replies": { + "type": "boolean" + }, + "associated_group_ids": { + "type": "array", + "items": {} + }, + "watching_category_ids": { + "type": "array", + "items": {} + }, + "tracking_category_ids": { + "type": "array", + "items": {} + }, + "watching_first_post_category_ids": { + "type": "array", + "items": {} + }, + "regular_category_ids": { + "type": "array", + "items": {} + }, + "muted_category_ids": { + "type": "array", + "items": {} + }, + "watching_tags": { + "type": "array", + "items": {} + }, + "watching_first_post_tags": { + "type": "array", + "items": {} + }, + "tracking_tags": { + "type": "array", + "items": {} + }, + "regular_tags": { + "type": "array", + "items": {} + }, + "muted_tags": { + "type": "array", + "items": {} + } + }, + "required": [ + "id", + "automatic", + "name", + "user_count", + "mentionable_level", + "messageable_level", + "visibility_level", + "primary_group", + "title", + "grant_trust_level", + "incoming_email", + "has_messages", + "flair_url", + "flair_bg_color", + "flair_color", + "bio_raw", + "bio_cooked", + "bio_excerpt", + "public_admission", + "public_exit", + "allow_membership_requests", + "full_name", + "default_notification_level", + "membership_request_template", + "is_group_user", + "members_visibility_level", + "can_see_members", + "can_admin_group", + "publish_read_state", + "is_group_owner_display", + "mentionable", + "messageable", + "automatic_membership_email_domains", + "smtp_server", + "smtp_port", + "smtp_ssl_mode", + "email_username", + "email_password", + "message_count", + "allow_unknown_sender_topic_replies", + "watching_category_ids", + "tracking_category_ids", + "watching_first_post_category_ids", + "regular_category_ids", + "muted_category_ids" + ] + }, + "extras": { + "type": "object", + "additionalProperties": false, + "properties": { + "visible_group_names": { + "type": "array", + "items": {} + } + }, + "required": [ + "visible_group_names" + ] + } + }, + "required": [ + "group", + "extras" + ] + } + } + } + } + } + } + }, + "/groups/{name}/members.json": { + "get": { + "summary": "List group members", + "tags": [ + "Groups" + ], + "operationId": "listGroupMembers", + "parameters": [ + { + "name": "name", + "in": "path", + "example": "name", + "description": "Use group name instead of id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "members": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "last_posted_at": { + "type": "string" + }, + "last_seen_at": { + "type": "string" + }, + "added_at": { + "type": "string" + }, + "timezone": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "title", + "last_posted_at", + "last_seen_at", + "added_at", + "timezone" + ] + } + }, + "owners": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "last_posted_at": { + "type": "string" + }, + "last_seen_at": { + "type": "string" + }, + "added_at": { + "type": "string" + }, + "timezone": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "title", + "last_posted_at", + "last_seen_at", + "added_at", + "timezone" + ] + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "total": { + "type": "integer" + }, + "limit": { + "type": "integer" + }, + "offset": { + "type": "integer" + } + }, + "required": [ + "total", + "limit", + "offset" + ] + } + }, + "required": [ + "members", + "owners", + "meta" + ] + } + } + } + } + } + } + }, + "/groups/{id}/members.json": { + "put": { + "summary": "Add group members", + "tags": [ + "Groups" + ], + "operationId": "addGroupMembers", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string" + }, + "usernames": { + "type": "array", + "items": {} + }, + "emails": { + "type": "array", + "items": {} + } + }, + "required": [ + "success", + "usernames", + "emails" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "usernames": { + "type": "string", + "description": "comma separated list", + "example": "username1,username2" + } + } + } + } + } + } + }, + "delete": { + "summary": "Remove group members", + "tags": [ + "Groups" + ], + "operationId": "removeGroupMembers", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string" + }, + "usernames": { + "type": "array", + "items": {} + }, + "skipped_usernames": { + "type": "array", + "items": {} + } + }, + "required": [ + "success", + "usernames", + "skipped_usernames" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "usernames": { + "type": "string", + "description": "comma separated list", + "example": "username1,username2" + } + } + } + } + } + } + } + }, + "/groups.json": { + "get": { + "summary": "List groups", + "tags": [ + "Groups" + ], + "operationId": "listGroups", + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "groups": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "automatic": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "user_count": { + "type": "integer" + }, + "mentionable_level": { + "type": "integer" + }, + "messageable_level": { + "type": "integer" + }, + "visibility_level": { + "type": "integer" + }, + "primary_group": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "grant_trust_level": { + "type": [ + "string", + "null" + ] + }, + "incoming_email": { + "type": [ + "string", + "null" + ] + }, + "has_messages": { + "type": "boolean" + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "bio_raw": { + "type": [ + "string", + "null" + ] + }, + "bio_cooked": { + "type": [ + "string", + "null" + ] + }, + "bio_excerpt": { + "type": [ + "string", + "null" + ] + }, + "public_admission": { + "type": "boolean" + }, + "public_exit": { + "type": "boolean" + }, + "allow_membership_requests": { + "type": "boolean" + }, + "full_name": { + "type": [ + "string", + "null" + ] + }, + "default_notification_level": { + "type": "integer" + }, + "membership_request_template": { + "type": [ + "string", + "null" + ] + }, + "is_group_user": { + "type": "boolean" + }, + "is_group_owner": { + "type": "boolean" + }, + "members_visibility_level": { + "type": "integer" + }, + "can_see_members": { + "type": "boolean" + }, + "can_admin_group": { + "type": "boolean" + }, + "can_edit_group": { + "type": "boolean" + }, + "publish_read_state": { + "type": "boolean" + } + }, + "required": [ + "id", + "automatic", + "name", + "display_name", + "user_count", + "mentionable_level", + "messageable_level", + "visibility_level", + "primary_group", + "title", + "grant_trust_level", + "incoming_email", + "has_messages", + "flair_url", + "flair_bg_color", + "flair_color", + "bio_raw", + "bio_cooked", + "bio_excerpt", + "public_admission", + "public_exit", + "allow_membership_requests", + "full_name", + "default_notification_level", + "membership_request_template", + "members_visibility_level", + "can_see_members", + "can_admin_group", + "publish_read_state" + ] + } + }, + "extras": { + "type": "object", + "additionalProperties": false, + "properties": { + "type_filters": { + "type": "array", + "items": {} + } + }, + "required": [ + "type_filters" + ] + }, + "total_rows_groups": { + "type": "integer" + }, + "load_more_groups": { + "type": "string" + } + }, + "required": [ + "groups", + "extras", + "total_rows_groups", + "load_more_groups" + ] + } + } + } + } + } + } + }, + "/invites.json": { + "post": { + "summary": "Create an invite", + "tags": [ + "Invites" + ], + "operationId": "createInvite", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "example": 42 + }, + "invite_key": { + "type": "string" + }, + "link": { + "type": "string", + "example": "http://example.com/invites/9045fd767efe201ca60c6658bcf14158" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "email": { + "type": "string", + "example": "not-a-user-yet@example.com" + }, + "domain": { + "type": [ + "string", + "null" + ] + }, + "emailed": { + "type": "boolean", + "example": false + }, + "can_delete_invite": { + "type": "boolean" + }, + "custom_message": { + "type": [ + "string", + "null" + ], + "example": "Hello world!" + }, + "created_at": { + "type": "string", + "example": "2021-01-01T12:00:00.000Z" + }, + "updated_at": { + "type": "string", + "example": "2021-01-01T12:00:00.000Z" + }, + "expires_at": { + "type": "string", + "example": "2021-02-01T12:00:00.000Z" + }, + "expired": { + "type": "boolean", + "example": false + }, + "topics": { + "type": "array", + "items": { + "type": "object" + }, + "example": [] + }, + "groups": { + "type": "array", + "items": { + "type": "object" + }, + "example": [] + } + }, + "required": [ + "id", + "invite_key", + "link", + "description", + "email", + "domain", + "emailed", + "can_delete_invite", + "custom_message", + "created_at", + "updated_at", + "expires_at", + "expired", + "topics", + "groups" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "email": { + "type": "string", + "example": "not-a-user-yet@example.com", + "description": "required for email invites only" + }, + "skip_email": { + "type": "boolean", + "default": false + }, + "custom_message": { + "type": "string", + "description": "optional, for email invites" + }, + "max_redemptions_allowed": { + "type": "integer", + "example": 5, + "default": 1, + "description": "optional, for link invites" + }, + "topic_id": { + "type": "integer" + }, + "group_ids": { + "type": "string", + "description": "Optional, either this or `group_names`. Comma separated\nlist for multiple ids.", + "example": "42,43" + }, + "group_names": { + "type": "string", + "description": "Optional, either this or `group_ids`. Comma separated\nlist for multiple names.", + "example": "foo,bar" + }, + "expires_at": { + "type": "string", + "description": "optional, if not supplied, the invite_expiry_days site\nsetting is used" + } + } + } + } + } + } + } + }, + "/invites/create-multiple.json": { + "post": { + "summary": "Create multiple invites", + "tags": [ + "Invites" + ], + "operationId": "createMultipleInvites", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "num_successfully_created_invitations": { + "type": "integer", + "example": 42 + }, + "num_failed_invitations": { + "type": "integer", + "example": 42 + }, + "failed_invitations": { + "type": "array", + "items": {}, + "example": [] + }, + "successful_invitations": { + "type": "array", + "example": [ + { + "id": 42, + "link": "http://example.com/invites/9045fd767efe201ca60c6658bcf14158", + "email": "not-a-user-yet-1@example.com", + "emailed": true, + "custom_message": "Hello world!", + "topics": [], + "groups": [], + "created_at": "2021-01-01T12:00:00.000Z", + "updated_at": "2021-01-01T12:00:00.000Z", + "expires_at": "2021-02-01T12:00:00.000Z", + "expired": false + }, + { + "id": 42, + "link": "http://example.com/invites/c6658bcf141589045fd767efe201ca60", + "email": "not-a-user-yet-2@example.com", + "emailed": true, + "custom_message": "Hello world!", + "topics": [], + "groups": [], + "created_at": "2021-01-01T12:00:00.000Z", + "updated_at": "2021-01-01T12:00:00.000Z", + "expires_at": "2021-02-01T12:00:00.000Z", + "expired": false + } + ] + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "example": [ + "not-a-user-yet-1@example.com", + "not-a-user-yet-2@example.com" + ], + "description": "pass 1 email per invite to be generated. other properties\nwill be shared by each invite." + }, + "skip_email": { + "type": "boolean", + "default": false + }, + "custom_message": { + "type": "string", + "description": "optional, for email invites" + }, + "max_redemptions_allowed": { + "type": "integer", + "example": 5, + "default": 1, + "description": "optional, for link invites" + }, + "topic_id": { + "type": "integer" + }, + "group_ids": { + "type": "string", + "description": "Optional, either this or `group_names`. Comma separated\nlist for multiple ids.", + "example": "42,43" + }, + "group_names": { + "type": "string", + "description": "Optional, either this or `group_ids`. Comma separated\nlist for multiple names.", + "example": "foo,bar" + }, + "expires_at": { + "type": "string", + "description": "optional, if not supplied, the invite_expiry_days site\nsetting is used" + } + } + } + } + } + } + } + }, + "/notifications.json": { + "get": { + "summary": "Get the notifications that belong to the current user", + "tags": [ + "Notifications" + ], + "operationId": "getNotifications", + "responses": { + "200": { + "description": "notifications", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "notifications": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "user_id": { + "type": "integer" + }, + "notification_type": { + "type": "integer" + }, + "read": { + "type": "boolean" + }, + "created_at": { + "type": "string" + }, + "post_number": { + "type": [ + "integer", + "null" + ] + }, + "topic_id": { + "type": [ + "integer", + "null" + ] + }, + "slug": { + "type": [ + "string", + "null" + ] + }, + "data": { + "type": "object", + "properties": { + "badge_id": { + "type": "integer" + }, + "badge_name": { + "type": "string" + }, + "badge_slug": { + "type": "string" + }, + "badge_title": { + "type": "boolean" + }, + "username": { + "type": "string" + } + } + } + } + } + }, + "total_rows_notifications": { + "type": "integer" + }, + "seen_notification_id": { + "type": "integer" + }, + "load_more_notifications": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/notifications/mark-read.json": { + "put": { + "summary": "Mark notifications as read", + "tags": [ + "Notifications" + ], + "operationId": "markNotificationsAsRead", + "parameters": [], + "responses": { + "200": { + "description": "notifications marked read", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "string" + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "(optional) Leave off to mark all notifications as\nread" + } + } + } + } + } + } + } + }, + "/posts.json": { + "get": { + "summary": "List latest posts across topics", + "tags": [ + "Posts" + ], + "operationId": "listPosts", + "parameters": [ + { + "name": "before", + "in": "query", + "required": false, + "description": "Load posts with an id lower than this value. Useful for pagination.", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "latest posts", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "latest_posts": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "username": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "cooked": { + "type": "string" + }, + "post_number": { + "type": "integer" + }, + "post_type": { + "type": "integer" + }, + "posts_count": { + "type": "integer" + }, + "updated_at": { + "type": "string" + }, + "reply_count": { + "type": "integer" + }, + "reply_to_post_number": { + "type": [ + "string", + "null" + ] + }, + "quote_count": { + "type": "integer" + }, + "incoming_link_count": { + "type": "integer" + }, + "reads": { + "type": "integer" + }, + "readers_count": { + "type": "integer" + }, + "score": { + "type": "number" + }, + "yours": { + "type": "boolean" + }, + "topic_id": { + "type": "integer" + }, + "topic_slug": { + "type": "string" + }, + "topic_title": { + "type": "string" + }, + "topic_html_title": { + "type": "string" + }, + "category_id": { + "type": "integer" + }, + "display_username": { + "type": [ + "string", + "null" + ] + }, + "primary_group_name": { + "type": [ + "string", + "null" + ] + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "flair_group_id": { + "type": [ + "string", + "null" + ] + }, + "badges_granted": { + "type": "array", + "items": {} + }, + "version": { + "type": "integer" + }, + "can_edit": { + "type": "boolean" + }, + "can_delete": { + "type": "boolean" + }, + "can_recover": { + "type": "boolean" + }, + "can_see_hidden_post": { + "type": "boolean" + }, + "can_wiki": { + "type": "boolean" + }, + "user_title": { + "type": [ + "string", + "null" + ] + }, + "bookmarked": { + "type": "boolean" + }, + "raw": { + "type": "string" + }, + "actions_summary": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "can_act": { + "type": "boolean" + } + }, + "required": [ + "id", + "can_act" + ] + } + }, + "moderator": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "staff": { + "type": "boolean" + }, + "user_id": { + "type": "integer" + }, + "hidden": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + }, + "deleted_at": { + "type": [ + "string", + "null" + ] + }, + "user_deleted": { + "type": "boolean" + }, + "edit_reason": { + "type": [ + "string", + "null" + ] + }, + "can_view_edit_history": { + "type": "boolean" + }, + "wiki": { + "type": "boolean" + }, + "excerpt": { + "type": "string" + }, + "truncated": { + "type": "boolean" + }, + "reviewable_id": { + "type": [ + "string", + "null" + ] + }, + "reviewable_score_count": { + "type": "integer" + }, + "reviewable_score_pending_count": { + "type": "integer" + }, + "post_url": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "username", + "avatar_template", + "created_at", + "cooked", + "post_number", + "post_type", + "posts_count", + "updated_at", + "reply_count", + "reply_to_post_number", + "quote_count", + "incoming_link_count", + "reads", + "readers_count", + "score", + "yours", + "topic_id", + "topic_slug", + "topic_title", + "topic_html_title", + "category_id", + "display_username", + "primary_group_name", + "flair_name", + "flair_url", + "flair_bg_color", + "flair_color", + "flair_group_id", + "badges_granted", + "version", + "can_edit", + "can_delete", + "can_recover", + "can_see_hidden_post", + "can_wiki", + "user_title", + "bookmarked", + "raw", + "actions_summary", + "moderator", + "admin", + "staff", + "user_id", + "hidden", + "trust_level", + "deleted_at", + "user_deleted", + "edit_reason", + "can_view_edit_history", + "wiki", + "excerpt", + "truncated", + "reviewable_id", + "reviewable_score_count", + "reviewable_score_pending_count", + "post_url" + ] + } + } + }, + "required": [ + "latest_posts" + ] + } + } + } + } + } + }, + "post": { + "summary": "Creates a new topic, a new post, or a private message", + "tags": [ + "Posts", + "Topics", + "Private Messages" + ], + "operationId": "createTopicPostPM", + "parameters": [], + "responses": { + "200": { + "description": "post created", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "username": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "cooked": { + "type": "string" + }, + "post_number": { + "type": "integer" + }, + "post_type": { + "type": "integer" + }, + "posts_count": { + "type": "integer" + }, + "updated_at": { + "type": "string" + }, + "reply_count": { + "type": "integer" + }, + "reply_to_post_number": { + "type": [ + "string", + "null" + ] + }, + "quote_count": { + "type": "integer" + }, + "incoming_link_count": { + "type": "integer" + }, + "reads": { + "type": "integer" + }, + "readers_count": { + "type": "integer" + }, + "score": { + "type": "number" + }, + "yours": { + "type": "boolean" + }, + "topic_id": { + "type": "integer" + }, + "topic_slug": { + "type": "string" + }, + "display_username": { + "type": [ + "string", + "null" + ] + }, + "primary_group_name": { + "type": [ + "string", + "null" + ] + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "flair_group_id": { + "type": [ + "integer", + "null" + ] + }, + "badges_granted": { + "type": "array", + "items": {} + }, + "version": { + "type": "integer" + }, + "can_edit": { + "type": "boolean" + }, + "can_delete": { + "type": "boolean" + }, + "can_recover": { + "type": "boolean" + }, + "can_see_hidden_post": { + "type": "boolean" + }, + "can_wiki": { + "type": "boolean" + }, + "user_title": { + "type": [ + "string", + "null" + ] + }, + "bookmarked": { + "type": "boolean" + }, + "actions_summary": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "can_act": { + "type": "boolean" + } + }, + "required": [ + "id", + "can_act" + ] + } + }, + "moderator": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "staff": { + "type": "boolean" + }, + "user_id": { + "type": "integer" + }, + "draft_sequence": { + "type": "integer" + }, + "hidden": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + }, + "deleted_at": { + "type": [ + "string", + "null" + ] + }, + "user_deleted": { + "type": "boolean" + }, + "edit_reason": { + "type": [ + "string", + "null" + ] + }, + "can_view_edit_history": { + "type": "boolean" + }, + "wiki": { + "type": "boolean" + }, + "reviewable_id": { + "type": [ + "integer", + "null" + ] + }, + "reviewable_score_count": { + "type": "integer" + }, + "reviewable_score_pending_count": { + "type": "integer" + }, + "post_url": { + "type": "string" + }, + "post_localizations": { + "type": "array", + "items": {} + }, + "mentioned_users": { + "type": "array", + "items": {} + } + }, + "required": [ + "id", + "name", + "username", + "avatar_template", + "created_at", + "cooked", + "post_number", + "post_type", + "posts_count", + "updated_at", + "reply_count", + "reply_to_post_number", + "quote_count", + "incoming_link_count", + "reads", + "readers_count", + "score", + "yours", + "topic_id", + "topic_slug", + "display_username", + "primary_group_name", + "flair_name", + "flair_url", + "flair_bg_color", + "flair_color", + "version", + "can_edit", + "can_delete", + "can_recover", + "can_wiki", + "user_title", + "bookmarked", + "actions_summary", + "moderator", + "admin", + "staff", + "user_id", + "draft_sequence", + "hidden", + "trust_level", + "deleted_at", + "user_deleted", + "edit_reason", + "can_view_edit_history", + "wiki", + "reviewable_id", + "reviewable_score_count", + "reviewable_score_pending_count", + "post_url" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "title": { + "type": "string", + "description": "Required if creating a new topic or new private message." + }, + "raw": { + "type": "string" + }, + "topic_id": { + "type": "integer", + "description": "Required if creating a new post." + }, + "category": { + "type": "integer", + "description": "Optional if creating a new topic, and ignored if creating\na new post." + }, + "target_recipients": { + "type": "string", + "description": "Required for private message, comma separated.", + "example": "blake,sam" + }, + "target_usernames": { + "type": "string", + "description": "Deprecated. Use target_recipients instead.", + "deprecated": true + }, + "archetype": { + "type": "string", + "description": "Required for new private message.", + "example": "private_message" + }, + "created_at": { + "type": "string" + }, + "reply_to_post_number": { + "type": "integer", + "description": "Optional, the post number to reply to inside a topic." + }, + "embed_url": { + "type": "string", + "description": "Provide a URL from a remote system to associate a forum\ntopic with that URL, typically for using Discourse as a comments\nsystem for an external blog." + }, + "external_id": { + "type": "string", + "description": "Provide an external_id from a remote system to associate\na forum topic with that id." + }, + "auto_track": { + "type": "boolean", + "description": "If false, the user will not track the topic. By default,\nthe user will track the topic." + } + }, + "required": [ + "raw" + ] + } + } + } + } + } + }, + "/posts/{id}.json": { + "get": { + "summary": "Retrieve a single post", + "tags": [ + "Posts" + ], + "operationId": "getPost", + "description": "This endpoint can be used to get the number of likes on a post using the\n`actions_summary` property in the response. `actions_summary` responses\nwith the id of `2` signify a `like`. If there are no `actions_summary`\nitems with the id of `2`, that means there are 0 likes. Other ids likely\nrefer to various different flag types.\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "single reviewable post", + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "cooked": { + "type": "string" + }, + "post_number": { + "type": "integer" + }, + "post_type": { + "type": "integer" + }, + "posts_count": { + "type": "integer" + }, + "updated_at": { + "type": "string" + }, + "reply_count": { + "type": "integer" + }, + "reply_to_post_number": { + "type": [ + "string", + "null" + ] + }, + "quote_count": { + "type": "integer" + }, + "incoming_link_count": { + "type": "integer" + }, + "reads": { + "type": "integer" + }, + "readers_count": { + "type": "integer" + }, + "score": { + "type": "number" + }, + "yours": { + "type": "boolean" + }, + "topic_id": { + "type": "integer" + }, + "topic_slug": { + "type": "string" + }, + "primary_group_name": { + "type": [ + "string", + "null" + ] + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "flair_group_id": { + "type": [ + "integer", + "null" + ] + }, + "version": { + "type": "integer" + }, + "can_edit": { + "type": "boolean" + }, + "can_delete": { + "type": "boolean" + }, + "can_recover": { + "type": "boolean" + }, + "can_see_hidden_post": { + "type": "boolean" + }, + "can_wiki": { + "type": "boolean" + }, + "user_title": { + "type": [ + "string", + "null" + ] + }, + "bookmarked": { + "type": "boolean" + }, + "raw": { + "type": "string" + }, + "actions_summary": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "`2`: like, `3`, `4`, `6`, `7`, `8`: flag" + }, + "count": { + "type": "integer" + }, + "acted": { + "type": "boolean" + }, + "can_undo": { + "type": "boolean" + }, + "can_act": { + "type": "boolean" + } + }, + "required": [ + "id" + ] + } + }, + "moderator": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "staff": { + "type": "boolean" + }, + "user_id": { + "type": "integer" + }, + "hidden": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + }, + "deleted_at": { + "type": [ + "string", + "null" + ] + }, + "user_deleted": { + "type": "boolean" + }, + "edit_reason": { + "type": [ + "string", + "null" + ] + }, + "can_view_edit_history": { + "type": "boolean" + }, + "wiki": { + "type": "boolean" + }, + "reviewable_id": { + "type": [ + "integer", + "null" + ] + }, + "reviewable_score_count": { + "type": "integer" + }, + "reviewable_score_pending_count": { + "type": "integer" + }, + "post_url": { + "type": "string" + }, + "mentioned_users": { + "type": "array", + "items": {} + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "display_username": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "username", + "avatar_template", + "created_at", + "cooked", + "post_number", + "post_type", + "posts_count", + "updated_at", + "reply_count", + "reply_to_post_number", + "quote_count", + "incoming_link_count", + "reads", + "readers_count", + "score", + "yours", + "topic_id", + "topic_slug", + "primary_group_name", + "flair_name", + "flair_url", + "flair_bg_color", + "flair_color", + "version", + "can_edit", + "can_delete", + "can_recover", + "can_wiki", + "user_title", + "bookmarked", + "raw", + "actions_summary", + "moderator", + "admin", + "staff", + "user_id", + "hidden", + "trust_level", + "deleted_at", + "user_deleted", + "edit_reason", + "can_view_edit_history", + "wiki", + "reviewable_id", + "reviewable_score_count", + "reviewable_score_pending_count", + "post_url" + ] + } + } + } + } + } + }, + "put": { + "summary": "Update a single post", + "tags": [ + "Posts" + ], + "operationId": "updatePost", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "post updated", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "post": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "cooked": { + "type": "string" + }, + "post_number": { + "type": "integer" + }, + "post_type": { + "type": "integer" + }, + "posts_count": { + "type": "integer" + }, + "updated_at": { + "type": "string" + }, + "reply_count": { + "type": "integer" + }, + "reply_to_post_number": { + "type": [ + "string", + "null" + ] + }, + "quote_count": { + "type": "integer" + }, + "incoming_link_count": { + "type": "integer" + }, + "reads": { + "type": "integer" + }, + "readers_count": { + "type": "integer" + }, + "score": { + "type": "number" + }, + "yours": { + "type": "boolean" + }, + "topic_id": { + "type": "integer" + }, + "topic_slug": { + "type": "string" + }, + "primary_group_name": { + "type": [ + "string", + "null" + ] + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "flair_group_id": { + "type": [ + "integer", + "null" + ] + }, + "badges_granted": { + "type": "array", + "items": {} + }, + "version": { + "type": "integer" + }, + "can_edit": { + "type": "boolean" + }, + "can_delete": { + "type": "boolean" + }, + "can_recover": { + "type": "boolean" + }, + "can_see_hidden_post": { + "type": "boolean" + }, + "can_wiki": { + "type": "boolean" + }, + "user_title": { + "type": [ + "string", + "null" + ] + }, + "bookmarked": { + "type": "boolean" + }, + "raw": { + "type": "string" + }, + "actions_summary": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "can_act": { + "type": "boolean" + } + }, + "required": [ + "id", + "can_act" + ] + } + }, + "moderator": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "staff": { + "type": "boolean" + }, + "user_id": { + "type": "integer" + }, + "draft_sequence": { + "type": "integer" + }, + "hidden": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + }, + "deleted_at": { + "type": [ + "string", + "null" + ] + }, + "user_deleted": { + "type": "boolean" + }, + "edit_reason": { + "type": [ + "string", + "null" + ] + }, + "can_view_edit_history": { + "type": "boolean" + }, + "wiki": { + "type": "boolean" + }, + "reviewable_id": { + "type": [ + "integer", + "null" + ] + }, + "reviewable_score_count": { + "type": "integer" + }, + "reviewable_score_pending_count": { + "type": "integer" + }, + "post_url": { + "type": "string" + }, + "post_localizations": { + "type": "array", + "items": {} + }, + "mentioned_users": { + "type": "array", + "items": {} + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "display_username": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "username", + "avatar_template", + "created_at", + "cooked", + "post_number", + "post_type", + "posts_count", + "updated_at", + "reply_count", + "reply_to_post_number", + "quote_count", + "incoming_link_count", + "reads", + "readers_count", + "score", + "yours", + "topic_id", + "topic_slug", + "primary_group_name", + "flair_name", + "flair_url", + "flair_bg_color", + "flair_color", + "version", + "can_edit", + "can_delete", + "can_recover", + "can_wiki", + "user_title", + "bookmarked", + "raw", + "actions_summary", + "moderator", + "admin", + "staff", + "user_id", + "draft_sequence", + "hidden", + "trust_level", + "deleted_at", + "user_deleted", + "edit_reason", + "can_view_edit_history", + "wiki", + "reviewable_id", + "reviewable_score_count", + "reviewable_score_pending_count", + "post_url" + ] + } + }, + "required": [ + "post" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "post": { + "type": "object", + "additionalProperties": false, + "properties": { + "raw": { + "type": "string" + }, + "edit_reason": { + "type": "string" + } + }, + "required": [ + "raw" + ] + }, + "bypass_bump": { + "type": "boolean", + "description": "Skip bumping the topic when updating the post. Requires\nstaff or TL4 permissions." + } + } + } + } + } + } + }, + "delete": { + "summary": "delete a single post", + "tags": [ + "Posts" + ], + "operationId": "deletePost", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "integer" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "success response" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "force_destroy": { + "type": "boolean", + "example": true, + "description": "The `SiteSetting.can_permanently_delete` needs to be\nenabled first before this param can be used. Also this endpoint\nneeds to be called first without `force_destroy` and then followed\nup with a second call 5 minutes later with `force_destroy` to\npermanently delete." + } + } + } + } + } + } + } + }, + "/posts/{id}/replies.json": { + "get": { + "summary": "List replies to a post", + "tags": [ + "Posts" + ], + "operationId": "postReplies", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "post replies", + "content": { + "application/json": { + "schema": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "username": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "cooked": { + "type": "string" + }, + "post_number": { + "type": "integer" + }, + "post_type": { + "type": "integer" + }, + "posts_count": { + "type": "integer" + }, + "updated_at": { + "type": "string" + }, + "reply_count": { + "type": "integer" + }, + "reply_to_post_number": { + "type": "integer" + }, + "quote_count": { + "type": "integer" + }, + "incoming_link_count": { + "type": "integer" + }, + "reads": { + "type": "integer" + }, + "readers_count": { + "type": "integer" + }, + "score": { + "type": "number" + }, + "yours": { + "type": "boolean" + }, + "topic_id": { + "type": "integer" + }, + "topic_slug": { + "type": "string" + }, + "display_username": { + "type": [ + "string", + "null" + ] + }, + "primary_group_name": { + "type": [ + "string", + "null" + ] + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "flair_group_id": { + "type": [ + "integer", + "null" + ] + }, + "version": { + "type": "integer" + }, + "can_edit": { + "type": "boolean" + }, + "can_delete": { + "type": "boolean" + }, + "can_recover": { + "type": "boolean" + }, + "can_see_hidden_post": { + "type": "boolean" + }, + "can_wiki": { + "type": "boolean" + }, + "user_title": { + "type": [ + "string", + "null" + ] + }, + "reply_to_user": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + }, + "required": [ + "username", + "avatar_template" + ] + }, + "bookmarked": { + "type": "boolean" + }, + "actions_summary": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "can_act": { + "type": "boolean" + } + }, + "required": [ + "id", + "can_act" + ] + } + }, + "moderator": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "staff": { + "type": "boolean" + }, + "user_id": { + "type": "integer" + }, + "hidden": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + }, + "deleted_at": { + "type": [ + "string", + "null" + ] + }, + "user_deleted": { + "type": "boolean" + }, + "edit_reason": { + "type": [ + "string", + "null" + ] + }, + "can_view_edit_history": { + "type": "boolean" + }, + "wiki": { + "type": "boolean" + }, + "reviewable_id": { + "type": [ + "integer", + "null" + ] + }, + "reviewable_score_count": { + "type": "integer" + }, + "reviewable_score_pending_count": { + "type": "integer" + }, + "post_url": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "username", + "avatar_template", + "created_at", + "cooked", + "post_number", + "post_type", + "posts_count", + "updated_at", + "reply_count", + "reply_to_post_number", + "quote_count", + "incoming_link_count", + "reads", + "readers_count", + "score", + "yours", + "topic_id", + "topic_slug", + "display_username", + "primary_group_name", + "flair_name", + "flair_url", + "flair_bg_color", + "flair_color", + "version", + "can_edit", + "can_delete", + "can_recover", + "can_see_hidden_post", + "can_wiki", + "user_title", + "reply_to_user", + "bookmarked", + "actions_summary", + "moderator", + "admin", + "staff", + "user_id", + "hidden", + "trust_level", + "deleted_at", + "user_deleted", + "edit_reason", + "can_view_edit_history", + "wiki", + "reviewable_id", + "reviewable_score_count", + "reviewable_score_pending_count", + "post_url" + ] + } + } + } + } + } + } + } + }, + "/posts/{id}/locked.json": { + "put": { + "summary": "Lock a post from being edited", + "tags": [ + "Posts" + ], + "operationId": "lockPost", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "post updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "locked": { + "type": "boolean", + "description": "Whether the post is locked" + } + }, + "required": [ + "locked" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "locked": { + "type": "string", + "description": "Whether to lock the post (true/false)" + } + }, + "required": [ + "locked" + ] + } + } + } + } + } + }, + "/post_actions.json": { + "post": { + "summary": "Like a post and other actions", + "tags": [ + "Posts" + ], + "operationId": "performPostAction", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "post updated", + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "properties": { + "id": { + "type": "integer", + "description": "The ID of the post" + }, + "name": { + "type": "string", + "description": "The name of the post author" + }, + "username": { + "type": "string", + "description": "The username of the post author" + }, + "avatar_template": { + "type": "string", + "description": "Template for the author's avatar URL" + }, + "created_at": { + "type": "string", + "description": "When the post was created" + }, + "cooked": { + "type": "string", + "description": "The HTML content of the post" + }, + "post_number": { + "type": "integer", + "description": "The post number within the topic" + }, + "post_type": { + "type": "integer", + "description": "The type of post" + }, + "posts_count": { + "type": "integer", + "description": "Total posts count for the user" + }, + "updated_at": { + "type": "string", + "description": "When the post was last updated" + }, + "reply_count": { + "type": "integer", + "description": "Number of replies to this post" + }, + "reply_to_post_number": { + "type": [ + "string", + "null" + ], + "description": "Post number this post is replying to" + }, + "quote_count": { + "type": "integer", + "description": "Number of times this post has been quoted" + }, + "incoming_link_count": { + "type": "integer", + "description": "Number of incoming links to this post" + }, + "reads": { + "type": "integer", + "description": "Number of reads" + }, + "readers_count": { + "type": "integer", + "description": "Number of readers" + }, + "score": { + "type": "number", + "description": "Post score" + }, + "yours": { + "type": "boolean", + "description": "Whether this post belongs to the current user" + }, + "topic_id": { + "type": "integer", + "description": "ID of the topic this post belongs to" + }, + "topic_slug": { + "type": "string", + "description": "Slug of the topic this post belongs to" + }, + "display_username": { + "type": "string", + "description": "Display username of the post author" + }, + "primary_group_name": { + "type": [ + "string", + "null" + ], + "description": "Primary group name of the author" + }, + "flair_name": { + "type": [ + "string", + "null" + ], + "description": "Flair name of the author" + }, + "flair_url": { + "type": [ + "string", + "null" + ], + "description": "Flair URL of the author" + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ], + "description": "Flair background color of the author" + }, + "flair_color": { + "type": [ + "string", + "null" + ], + "description": "Flair color of the author" + }, + "flair_group_id": { + "type": [ + "integer", + "null" + ], + "description": "Flair group ID of the author" + }, + "badges_granted": { + "type": "array", + "description": "Badges granted to the user" + }, + "version": { + "type": "integer", + "description": "Version number of the post" + }, + "can_edit": { + "type": "boolean", + "description": "Whether the current user can edit this post" + }, + "can_delete": { + "type": "boolean", + "description": "Whether the current user can delete this post" + }, + "can_recover": { + "type": "boolean", + "description": "Whether the current user can recover this post" + }, + "can_see_hidden_post": { + "type": "boolean", + "description": "Whether the current user can see hidden posts" + }, + "can_wiki": { + "type": "boolean", + "description": "Whether the current user can wiki this post" + }, + "user_title": { + "type": [ + "string", + "null" + ], + "description": "Title of the post author" + }, + "bookmarked": { + "type": "boolean", + "description": "Whether the post is bookmarked by the current user" + }, + "actions_summary": { + "type": "array", + "description": "Summary of actions performed on this post", + "items": { + "type": "object", + "additionalProperties": true, + "properties": { + "id": { + "type": "integer", + "description": "ID of the action type (e.g., 2 for like)" + }, + "count": { + "type": "integer", + "description": "Number of times this action has been performed" + }, + "acted": { + "type": "boolean", + "description": "Whether the current user has performed this\naction" + }, + "can_undo": { + "type": "boolean", + "description": "Whether the current user can undo this action" + }, + "can_act": { + "type": "boolean", + "description": "Whether the current user can perform this action" + } + } + } + }, + "moderator": { + "type": "boolean", + "description": "Whether the post author is a moderator" + }, + "admin": { + "type": "boolean", + "description": "Whether the post author is an admin" + }, + "staff": { + "type": "boolean", + "description": "Whether the post author is staff" + }, + "user_id": { + "type": "integer", + "description": "ID of the post author" + }, + "hidden": { + "type": "boolean", + "description": "Whether the post is hidden" + }, + "trust_level": { + "type": "integer", + "description": "Trust level of the post author" + }, + "deleted_at": { + "type": [ + "string", + "null" + ], + "description": "When the post was deleted" + }, + "user_deleted": { + "type": "boolean", + "description": "Whether the post was deleted by the user" + }, + "edit_reason": { + "type": [ + "string", + "null" + ], + "description": "Reason for the last edit" + }, + "can_view_edit_history": { + "type": "boolean", + "description": "Whether the current user can view edit history" + }, + "wiki": { + "type": "boolean", + "description": "Whether this is a wiki post" + }, + "reviewable_id": { + "type": [ + "integer", + "null" + ], + "description": "ID of the reviewable if this post is under review" + }, + "reviewable_score_count": { + "type": "integer", + "description": "Number of reviewable scores" + }, + "reviewable_score_pending_count": { + "type": "integer", + "description": "Number of pending reviewable scores" + }, + "post_url": { + "type": "string", + "description": "URL of the post" + } + }, + "required": [ + "id", + "name", + "username", + "avatar_template", + "created_at", + "cooked", + "post_number", + "post_type", + "posts_count", + "updated_at", + "reply_count", + "reply_to_post_number", + "quote_count", + "incoming_link_count", + "reads", + "readers_count", + "score", + "yours", + "topic_id", + "topic_slug", + "display_username", + "primary_group_name", + "flair_name", + "flair_url", + "flair_bg_color", + "flair_color", + "flair_group_id", + "badges_granted", + "version", + "can_edit", + "can_delete", + "can_recover", + "can_see_hidden_post", + "can_wiki", + "user_title", + "bookmarked", + "actions_summary", + "moderator", + "admin", + "staff", + "user_id", + "hidden", + "trust_level", + "deleted_at", + "user_deleted", + "edit_reason", + "can_view_edit_history", + "wiki", + "reviewable_id", + "reviewable_score_count", + "reviewable_score_pending_count", + "post_url" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "The ID of the post to perform the action on" + }, + "post_action_type_id": { + "type": "integer", + "description": "The ID of the post action type (e.g., 2 for like)" + }, + "flag_topic": { + "type": "boolean", + "description": "Whether to flag the entire topic" + } + }, + "required": [ + "id", + "post_action_type_id" + ] + } + } + } + } + } + }, + "/topics/private-messages/{username}.json": { + "get": { + "summary": "Get a list of private messages for a user", + "tags": [ + "Private Messages" + ], + "operationId": "listUserPrivateMessages", + "parameters": [ + { + "name": "username", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "private messages", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + } + } + }, + "primary_groups": { + "type": "array", + "items": {} + }, + "topic_list": { + "type": "object", + "properties": { + "can_create_topic": { + "type": "boolean" + }, + "draft": { + "type": [ + "string", + "null" + ] + }, + "draft_key": { + "type": "string" + }, + "draft_sequence": { + "type": "integer" + }, + "per_page": { + "type": "integer" + }, + "topics": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "fancy_title": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "posts_count": { + "type": "integer" + }, + "reply_count": { + "type": "integer" + }, + "highest_post_number": { + "type": "integer" + }, + "image_url": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "last_posted_at": { + "type": "string" + }, + "bumped": { + "type": "boolean" + }, + "bumped_at": { + "type": "string" + }, + "archetype": { + "type": "string" + }, + "unseen": { + "type": "boolean" + }, + "last_read_post_number": { + "type": "integer" + }, + "unread_posts": { + "type": "integer" + }, + "pinned": { + "type": "boolean" + }, + "unpinned": { + "type": [ + "string", + "null" + ] + }, + "visible": { + "type": "boolean" + }, + "closed": { + "type": "boolean" + }, + "archived": { + "type": "boolean" + }, + "notification_level": { + "type": "integer" + }, + "bookmarked": { + "type": "boolean" + }, + "liked": { + "type": "boolean" + }, + "views": { + "type": "integer" + }, + "like_count": { + "type": "integer" + }, + "has_summary": { + "type": "boolean" + }, + "last_poster_username": { + "type": "string" + }, + "category_id": { + "type": [ + "string", + "null" + ] + }, + "pinned_globally": { + "type": "boolean" + }, + "featured_link": { + "type": [ + "string", + "null" + ] + }, + "allowed_user_count": { + "type": "integer" + }, + "posters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "extras": { + "type": "string" + }, + "description": { + "type": "string" + }, + "user_id": { + "type": "integer" + }, + "primary_group_id": { + "type": [ + "integer", + "null" + ] + } + } + } + }, + "participants": { + "type": "array", + "items": { + "type": "object", + "properties": { + "extras": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "user_id": { + "type": "integer" + }, + "primary_group_id": { + "type": [ + "integer", + "null" + ] + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/topics/private-messages-sent/{username}.json": { + "get": { + "summary": "Get a list of private messages sent for a user", + "tags": [ + "Private Messages" + ], + "operationId": "getUserSentPrivateMessages", + "parameters": [ + { + "name": "username", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "private messages", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + } + } + } + }, + "primary_groups": { + "type": "array", + "items": {} + }, + "topic_list": { + "type": "object", + "properties": { + "can_create_topic": { + "type": "boolean" + }, + "draft": { + "type": [ + "string", + "null" + ] + }, + "draft_key": { + "type": "string" + }, + "draft_sequence": { + "type": "integer" + }, + "per_page": { + "type": "integer" + }, + "topics": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "fancy_title": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "posts_count": { + "type": "integer" + }, + "reply_count": { + "type": "integer" + }, + "highest_post_number": { + "type": "integer" + }, + "image_url": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "last_posted_at": { + "type": "string" + }, + "bumped": { + "type": "boolean" + }, + "bumped_at": { + "type": "string" + }, + "archetype": { + "type": "string" + }, + "unseen": { + "type": "boolean" + }, + "last_read_post_number": { + "type": "integer" + }, + "unread_posts": { + "type": "integer" + }, + "pinned": { + "type": "boolean" + }, + "unpinned": { + "type": [ + "string", + "null" + ] + }, + "visible": { + "type": "boolean" + }, + "closed": { + "type": "boolean" + }, + "archived": { + "type": "boolean" + }, + "notification_level": { + "type": "integer" + }, + "bookmarked": { + "type": "boolean" + }, + "liked": { + "type": "boolean" + }, + "views": { + "type": "integer" + }, + "like_count": { + "type": "integer" + }, + "has_summary": { + "type": "boolean" + }, + "last_poster_username": { + "type": "string" + }, + "category_id": { + "type": [ + "string", + "null" + ] + }, + "pinned_globally": { + "type": "boolean" + }, + "featured_link": { + "type": [ + "string", + "null" + ] + }, + "allowed_user_count": { + "type": "integer" + }, + "posters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "extras": { + "type": "string" + }, + "description": { + "type": "string" + }, + "user_id": { + "type": "integer" + }, + "primary_group_id": { + "type": [ + "integer", + "null" + ] + } + } + } + }, + "participants": { + "type": "array", + "items": {} + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/search.json": { + "get": { + "summary": "Search for a term", + "tags": [ + "Search" + ], + "operationId": "search", + "parameters": [ + { + "name": "q", + "in": "query", + "example": "api @blake #support tags:api after:2021-06-04 in:unseen in:open\norder:latest_topic", + "description": "The query string needs to be url encoded and is made up of the following options:\n- Search term. This is just a string. Usually it would be the first item in the query.\n- `@`: Use the `@` followed by the username to specify posts by this user.\n- `#`: Use the `#` followed by the category slug to search within this category.\n- `tags:`: `api,solved` or for posts that have all the specified tags `api+solved`.\n- `before:`: `yyyy-mm-dd`\n- `after:`: `yyyy-mm-dd`\n- `order:`: `latest`, `likes`, `views`, `latest_topic`\n- `assigned:`: username (without `@`)\n- `in:`: `title`, `likes`, `personal`, `messages`, `seen`, `unseen`, `posted`, `created`, `watching`, `tracking`, `bookmarks`, `assigned`, `unassigned`, `first`, `pinned`, `wiki`\n- `with:`: `images`\n- `status:`: `open`, `closed`, `public`, `archived`, `noreplies`, `single_user`, `solved`, `unsolved`\n- `group:`: group_name or group_id\n- `group_messages:`: group_name or group_id\n- `min_posts:`: 1\n- `max_posts:`: 10\n- `min_views:`: 1\n- `max_views:`: 10\n\nIf you are using cURL you can use the `-G` and the `--data-urlencode` flags to encode the query:\n\n```\ncurl -i -sS -X GET -G \"http://localhost:4200/search.json\" \\\n--data-urlencode 'q=wordpress @scossar #fun after:2020-01-01'\n```\n", + "schema": { + "type": "string" + } + }, + { + "name": "page", + "in": "query", + "example": 1, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "posts": { + "type": "array", + "items": {} + }, + "users": { + "type": "array", + "items": {} + }, + "categories": { + "type": "array", + "items": {} + }, + "tags": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "slug" + ] + } + }, + "groups": { + "type": "array", + "items": {} + }, + "grouped_search_result": { + "type": "object", + "additionalProperties": false, + "properties": { + "more_posts": { + "type": [ + "string", + "null" + ] + }, + "more_users": { + "type": [ + "string", + "null" + ] + }, + "more_categories": { + "type": [ + "string", + "null" + ] + }, + "term": { + "type": "string" + }, + "search_log_id": { + "type": "integer" + }, + "more_full_page_results": { + "type": [ + "string", + "null" + ] + }, + "can_create_topic": { + "type": "boolean" + }, + "error": { + "type": [ + "string", + "null" + ] + }, + "extra": { + "type": "object", + "properties": { + "categories": { + "type": [ + "array", + "null" + ] + } + } + }, + "post_ids": { + "type": "array", + "items": {} + }, + "user_ids": { + "type": "array", + "items": {} + }, + "category_ids": { + "type": "array", + "items": {} + }, + "tag_ids": { + "type": "array", + "items": {} + }, + "group_ids": { + "type": "array", + "items": {} + } + }, + "required": [ + "more_posts", + "more_users", + "more_categories", + "term", + "search_log_id", + "more_full_page_results", + "can_create_topic", + "error", + "post_ids", + "user_ids", + "category_ids", + "tag_ids", + "group_ids" + ] + } + }, + "required": [ + "posts", + "users", + "categories", + "tags", + "groups", + "grouped_search_result" + ] + } + } + } + } + } + } + }, + "/site.json": { + "get": { + "summary": "Get site info", + "tags": [ + "Site", + "Categories" + ], + "operationId": "getSite", + "description": "Can be used to fetch all categories and subcategories", + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "default_archetype": { + "type": "string" + }, + "notification_types": { + "type": "object", + "additionalProperties": false, + "properties": { + "mentioned": { + "type": "integer" + }, + "replied": { + "type": "integer" + }, + "quoted": { + "type": "integer" + }, + "edited": { + "type": "integer" + }, + "liked": { + "type": "integer" + }, + "private_message": { + "type": "integer" + }, + "invited_to_private_message": { + "type": "integer" + }, + "invitee_accepted": { + "type": "integer" + }, + "posted": { + "type": "integer" + }, + "watching_category_or_tag": { + "type": "integer" + }, + "new_features": { + "type": "integer" + }, + "admin_problems": { + "type": "integer" + }, + "moved_post": { + "type": "integer" + }, + "linked": { + "type": "integer" + }, + "granted_badge": { + "type": "integer" + }, + "invited_to_topic": { + "type": "integer" + }, + "custom": { + "type": "integer" + }, + "group_mentioned": { + "type": "integer" + }, + "group_message_summary": { + "type": "integer" + }, + "watching_first_post": { + "type": "integer" + }, + "topic_reminder": { + "type": "integer" + }, + "liked_consolidated": { + "type": "integer" + }, + "linked_consolidated": { + "type": "integer" + }, + "post_approved": { + "type": "integer" + }, + "code_review_commit_approved": { + "type": "integer" + }, + "membership_request_accepted": { + "type": "integer" + }, + "membership_request_consolidated": { + "type": "integer" + }, + "bookmark_reminder": { + "type": "integer" + }, + "reaction": { + "type": "integer" + }, + "votes_released": { + "type": "integer" + }, + "event_reminder": { + "type": "integer" + }, + "event_invitation": { + "type": "integer" + }, + "chat_mention": { + "type": "integer" + }, + "chat_message": { + "type": "integer" + }, + "chat_invitation": { + "type": "integer" + }, + "chat_group_mention": { + "type": "integer" + }, + "chat_quoted": { + "type": "integer" + }, + "chat_watched_thread": { + "type": "integer" + }, + "upcoming_change_available": { + "type": "integer" + }, + "upcoming_change_automatically_promoted": { + "type": "integer" + }, + "assigned": { + "type": "integer" + }, + "question_answer_user_commented": { + "type": "integer" + }, + "following": { + "type": "integer" + }, + "following_created_topic": { + "type": "integer" + }, + "following_replied": { + "type": "integer" + }, + "circles_activity": { + "type": "integer" + }, + "boost": { + "type": "integer" + }, + "suggested_edit_created": { + "type": "integer" + }, + "suggested_edit_accepted": { + "type": "integer" + } + }, + "required": [ + "mentioned", + "replied", + "quoted", + "edited", + "liked", + "private_message", + "invited_to_private_message", + "invitee_accepted", + "posted", + "watching_category_or_tag", + "moved_post", + "linked", + "granted_badge", + "invited_to_topic", + "custom", + "group_mentioned", + "group_message_summary", + "watching_first_post", + "topic_reminder", + "liked_consolidated", + "linked_consolidated", + "post_approved", + "code_review_commit_approved", + "membership_request_accepted", + "membership_request_consolidated", + "bookmark_reminder", + "reaction", + "votes_released", + "event_reminder", + "event_invitation", + "chat_mention", + "chat_message", + "chat_invitation", + "chat_group_mention" + ] + }, + "post_types": { + "type": "object", + "additionalProperties": false, + "properties": { + "regular": { + "type": "integer" + }, + "moderator_action": { + "type": "integer" + }, + "small_action": { + "type": "integer" + }, + "whisper": { + "type": "integer" + } + }, + "required": [ + "regular", + "moderator_action", + "small_action", + "whisper" + ] + }, + "trust_levels": { + "type": "object", + "additionalProperties": false, + "properties": { + "newuser": { + "type": "integer" + }, + "basic": { + "type": "integer" + }, + "member": { + "type": "integer" + }, + "regular": { + "type": "integer" + }, + "leader": { + "type": "integer" + } + }, + "required": [ + "newuser", + "basic", + "member", + "regular", + "leader" + ] + }, + "user_tips": { + "type": "object", + "additionalProperties": false, + "properties": { + "first_notification": { + "type": "integer" + }, + "topic_timeline": { + "type": "integer" + }, + "post_menu": { + "type": "integer" + }, + "topic_notification_levels": { + "type": "integer" + }, + "suggested_topics": { + "type": "integer" + } + }, + "required": [ + "first_notification", + "topic_timeline", + "post_menu", + "topic_notification_levels", + "suggested_topics" + ] + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "automatic": { + "type": [ + "boolean" + ] + } + }, + "required": [ + "id", + "name", + "flair_url", + "flair_bg_color", + "flair_color", + "automatic" + ] + } + }, + "filters": { + "type": "array", + "items": {} + }, + "periods": { + "type": "array", + "items": {} + }, + "top_menu_items": { + "type": "array", + "items": {} + }, + "anonymous_top_menu_items": { + "type": "array", + "items": {} + }, + "uncategorized_category_id": { + "type": "integer" + }, + "user_field_max_length": { + "type": "integer" + }, + "post_action_types": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": [ + "integer", + "null" + ] + }, + "name_key": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "short_description": { + "type": "string" + }, + "is_flag": { + "type": "boolean" + }, + "require_message": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "applies_to": { + "type": "array" + }, + "is_used": { + "type": "boolean" + }, + "position": { + "type": "integer" + }, + "auto_action_type": { + "type": "boolean" + }, + "system": { + "type": "boolean" + } + }, + "required": [ + "id", + "name_key", + "name", + "description", + "short_description", + "is_flag", + "require_message", + "enabled", + "applies_to", + "is_used", + "auto_action_type" + ] + } + }, + "topic_flag_types": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": [ + "integer", + "null" + ] + }, + "name_key": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "short_description": { + "type": "string" + }, + "is_flag": { + "type": "boolean" + }, + "require_message": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "applies_to": { + "type": "array" + }, + "is_used": { + "type": "boolean" + }, + "position": { + "type": "integer" + }, + "auto_action_type": { + "type": "boolean" + }, + "system": { + "type": "boolean" + } + }, + "required": [ + "id", + "name_key", + "name", + "description", + "short_description", + "is_flag", + "require_message", + "enabled", + "applies_to", + "is_used", + "auto_action_type" + ] + } + }, + "can_create_tag": { + "type": "boolean" + }, + "can_tag_topics": { + "type": "boolean" + }, + "can_tag_pms": { + "type": "boolean" + }, + "tags_filter_regexp": { + "type": "string" + }, + "top_tags": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "slug" + ] + } + }, + "wizard_required": { + "type": "boolean" + }, + "can_associate_groups": { + "type": "boolean" + }, + "email_configured": { + "type": "boolean" + }, + "topic_featured_link_allowed_category_ids": { + "type": "array", + "items": {} + }, + "user_themes": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "theme_id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "default": { + "type": "boolean" + }, + "color_scheme_id": { + "type": [ + "integer", + "null" + ] + }, + "dark_color_scheme_id": { + "type": [ + "integer", + "null" + ] + }, + "only_theme_color_schemes": { + "type": "boolean" + } + }, + "required": [ + "theme_id", + "name", + "default", + "color_scheme_id" + ] + } + }, + "user_color_schemes": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "is_dark": { + "type": "boolean" + }, + "theme_id": { + "type": [ + "integer", + "null" + ] + }, + "colors": { + "type": "array" + } + }, + "required": [ + "id", + "name", + "is_dark", + "colors" + ] + } + }, + "default_light_color_scheme": { + "type": [ + "object", + "null" + ] + }, + "default_dark_color_scheme": { + "type": [ + "object", + "null" + ] + }, + "censored_regexp": { + "type": "array", + "items": { + "type": "object" + } + }, + "custom_emoji_translation": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "watched_words_replace": { + "type": [ + "string", + "null" + ] + }, + "watched_words_link": { + "type": [ + "string", + "null" + ] + }, + "markdown_additional_options": { + "type": "object" + }, + "hashtag_configurations": { + "type": "object" + }, + "hashtag_icons": { + "type": "object" + }, + "displayed_about_plugin_stat_groups": { + "type": "array" + }, + "categories": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "color": { + "type": "string" + }, + "text_color": { + "type": "string" + }, + "style_type": { + "type": "string" + }, + "emoji": { + "type": [ + "string", + "null" + ] + }, + "icon": { + "type": [ + "string", + "null" + ] + }, + "slug": { + "type": "string" + }, + "topic_count": { + "type": "integer" + }, + "post_count": { + "type": "integer" + }, + "position": { + "type": "integer" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "description_text": { + "type": [ + "string", + "null" + ] + }, + "description_excerpt": { + "type": [ + "string", + "null" + ] + }, + "topic_url": { + "type": "string" + }, + "read_restricted": { + "type": "boolean" + }, + "permission": { + "type": "integer" + }, + "notification_level": { + "type": "integer" + }, + "topic_template": { + "type": [ + "string", + "null" + ] + }, + "topic_title_placeholder": { + "type": [ + "string", + "null" + ] + }, + "has_children": { + "type": "boolean" + }, + "subcategory_count": { + "type": [ + "integer", + "null" + ] + }, + "sort_order": { + "type": [ + "string", + "null" + ] + }, + "sort_ascending": { + "type": [ + "string", + "null" + ] + }, + "show_subcategory_list": { + "type": "boolean" + }, + "num_featured_topics": { + "type": "integer" + }, + "default_view": { + "type": [ + "string", + "null" + ] + }, + "subcategory_list_style": { + "type": "string" + }, + "default_top_period": { + "type": "string" + }, + "default_list_filter": { + "type": "string" + }, + "minimum_required_tags": { + "type": "integer" + }, + "navigate_to_first_post_after_read": { + "type": "boolean" + }, + "allowed_tags": { + "type": "array", + "items": {} + }, + "allowed_tag_groups": { + "type": "array", + "items": {} + }, + "allow_global_tags": { + "type": "boolean" + }, + "required_tag_groups": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "min_count": { + "type": "integer" + } + }, + "required": [ + "name", + "min_count" + ] + } + }, + "read_only_banner": { + "type": [ + "string", + "null" + ] + }, + "uploaded_logo": { + "type": [ + "string", + "null" + ] + }, + "uploaded_logo_dark": { + "type": [ + "string", + "null" + ] + }, + "uploaded_background": { + "type": [ + "string", + "null" + ] + }, + "uploaded_background_dark": { + "type": [ + "string", + "null" + ] + }, + "can_edit": { + "type": "boolean" + }, + "custom_fields": { + "type": [ + "object", + "null" + ], + "additionalProperties": true + }, + "parent_category_id": { + "type": "integer" + }, + "form_template_ids": { + "type": "array", + "items": {} + } + }, + "required": [ + "id", + "name", + "color", + "text_color", + "slug", + "topic_count", + "post_count", + "position", + "topic_url", + "read_restricted", + "permission", + "notification_level", + "topic_template", + "topic_title_placeholder", + "has_children", + "subcategory_count", + "sort_order", + "sort_ascending", + "show_subcategory_list", + "num_featured_topics", + "default_view", + "subcategory_list_style", + "default_top_period", + "default_list_filter", + "minimum_required_tags", + "navigate_to_first_post_after_read", + "allowed_tags", + "allowed_tag_groups", + "allow_global_tags", + "required_tag_groups", + "read_only_banner", + "uploaded_logo", + "uploaded_logo_dark", + "uploaded_background", + "uploaded_background_dark", + "can_edit" + ] + } + }, + "archetypes": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "options": { + "type": "array", + "items": {} + } + }, + "required": [ + "id", + "name", + "options" + ] + } + }, + "user_fields": { + "type": "array", + "items": {} + }, + "auth_providers": { + "type": "array", + "items": {} + }, + "whispers_allowed_groups_names": { + "type": "array" + }, + "denied_emojis": { + "type": "array" + }, + "valid_flag_applies_to_types": { + "type": "array" + }, + "navigation_menu_site_top_tags": { + "type": "array" + }, + "full_name_required_for_signup": { + "type": "boolean" + }, + "full_name_visible_in_signup": { + "type": "boolean" + }, + "admin_config_login_routes": { + "type": "array" + } + }, + "required": [ + "default_archetype", + "notification_types", + "post_types", + "trust_levels", + "groups", + "filters", + "periods", + "top_menu_items", + "anonymous_top_menu_items", + "uncategorized_category_id", + "user_field_max_length", + "post_action_types", + "topic_flag_types", + "can_create_tag", + "can_tag_topics", + "can_tag_pms", + "tags_filter_regexp", + "top_tags", + "topic_featured_link_allowed_category_ids", + "user_themes", + "user_color_schemes", + "default_light_color_scheme", + "default_dark_color_scheme", + "censored_regexp", + "custom_emoji_translation", + "watched_words_replace", + "watched_words_link", + "categories", + "archetypes", + "user_fields", + "auth_providers", + "full_name_required_for_signup", + "full_name_visible_in_signup", + "email_configured" + ] + } + } + } + } + } + } + }, + "/site/basic-info.json": { + "get": { + "summary": "Get site basic info", + "tags": [ + "Site" + ], + "operationId": "getSiteBasicInfo", + "description": "Can be used to fetch basic info about a site", + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "logo_url": { + "type": "string" + }, + "logo_small_url": { + "type": "string" + }, + "apple_touch_icon_url": { + "type": "string" + }, + "favicon_url": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "header_primary_color": { + "type": "string" + }, + "header_background_color": { + "type": "string" + }, + "login_required": { + "type": "boolean" + }, + "locale": { + "type": "string" + }, + "include_in_discourse_discover": { + "type": "boolean" + }, + "mobile_logo_url": { + "type": "string" + } + }, + "required": [ + "logo_url", + "logo_small_url", + "apple_touch_icon_url", + "favicon_url", + "title", + "description", + "header_primary_color", + "header_background_color", + "login_required", + "locale", + "include_in_discourse_discover", + "mobile_logo_url" + ] + } + } + } + } + } + } + }, + "/tag_groups.json": { + "get": { + "summary": "Get a list of tag groups", + "tags": [ + "Tags" + ], + "operationId": "listTagGroups", + "responses": { + "200": { + "description": "tags", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "tag_groups": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "slug" + ] + } + }, + "parent_tag": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "slug" + ] + } + }, + "one_per_topic": { + "type": "boolean" + }, + "permissions": { + "type": "object", + "additionalProperties": { + "type": "integer" + } + } + }, + "required": [ + "id", + "name", + "tags", + "parent_tag", + "one_per_topic", + "permissions" + ] + } + } + }, + "required": [ + "tag_groups" + ] + } + } + } + } + } + }, + "post": { + "summary": "Creates a tag group", + "tags": [ + "Tags" + ], + "operationId": "createTagGroup", + "parameters": [], + "responses": { + "200": { + "description": "tag group created", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "tag_group": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "slug" + ] + } + }, + "parent_tag": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "slug" + ] + } + }, + "one_per_topic": { + "type": "boolean" + }, + "permissions": { + "type": "object" + } + }, + "required": [ + "id", + "name", + "tags", + "parent_tag", + "one_per_topic", + "permissions" + ] + } + }, + "required": [ + "tag_group" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } + } + } + }, + "/tag_groups/{id}.json": { + "get": { + "summary": "Get a single tag group", + "tags": [ + "Tags" + ], + "operationId": "getTagGroup", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "notifications", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "tag_group": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag_names": { + "type": "array", + "items": {} + }, + "parent_tag_name": { + "type": "array", + "items": {} + }, + "one_per_topic": { + "type": "boolean" + }, + "permissions": { + "type": "object", + "properties": { + "everyone": { + "type": "integer" + } + } + } + } + } + } + } + } + } + } + } + }, + "put": { + "summary": "Update tag group", + "tags": [ + "Tags" + ], + "operationId": "updateTagGroup", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "Tag group updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "string" + }, + "tag_group": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag_names": { + "type": "array", + "items": {} + }, + "parent_tag_name": { + "type": "array", + "items": {} + }, + "one_per_topic": { + "type": "boolean" + }, + "permissions": { + "type": "object", + "properties": { + "everyone": { + "type": "integer" + } + } + } + } + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + } + } + } + } + }, + "/tags.json": { + "get": { + "summary": "Get a list of tags", + "tags": [ + "Tags" + ], + "operationId": "listTags", + "responses": { + "200": { + "description": "notifications", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "tags": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "text": { + "type": "string" + }, + "name": { + "type": "string" + }, + "count": { + "type": "integer" + }, + "pm_count": { + "type": "integer" + }, + "target_tag": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "extras": { + "type": "object", + "properties": { + "categories": { + "type": "array", + "items": {} + } + } + } + } + } + } + } + } + } + } + }, + "/tag/{name}.json": { + "get": { + "summary": "Get a specific tag", + "tags": [ + "Tags" + ], + "operationId": "getTag", + "parameters": [ + { + "name": "name", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "notifications", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + } + } + } + }, + "primary_groups": { + "type": "array", + "items": {} + }, + "topic_list": { + "type": "object", + "properties": { + "can_create_topic": { + "type": "boolean" + }, + "draft": { + "type": [ + "string", + "null" + ] + }, + "draft_key": { + "type": "string" + }, + "draft_sequence": { + "type": "integer" + }, + "per_page": { + "type": "integer" + }, + "tags": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "topic_count": { + "type": "integer" + }, + "staff": { + "type": "boolean" + } + } + } + }, + "topics": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "fancy_title": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "posts_count": { + "type": "integer" + }, + "reply_count": { + "type": "integer" + }, + "highest_post_number": { + "type": "integer" + }, + "image_url": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "last_posted_at": { + "type": "string" + }, + "bumped": { + "type": "boolean" + }, + "bumped_at": { + "type": "string" + }, + "archetype": { + "type": "string" + }, + "unseen": { + "type": "boolean" + }, + "last_read_post_number": { + "type": "integer" + }, + "unread_posts": { + "type": "integer" + }, + "pinned": { + "type": "boolean" + }, + "unpinned": { + "type": [ + "string", + "null" + ] + }, + "visible": { + "type": "boolean" + }, + "closed": { + "type": "boolean" + }, + "archived": { + "type": "boolean" + }, + "notification_level": { + "type": "integer" + }, + "bookmarked": { + "type": "boolean" + }, + "liked": { + "type": "boolean" + }, + "tags": { + "type": "array", + "items": {} + }, + "views": { + "type": "integer" + }, + "like_count": { + "type": "integer" + }, + "has_summary": { + "type": "boolean" + }, + "last_poster_username": { + "type": "string" + }, + "category_id": { + "type": "integer" + }, + "pinned_globally": { + "type": "boolean" + }, + "featured_link": { + "type": [ + "string", + "null" + ] + }, + "posters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "extras": { + "type": "string" + }, + "description": { + "type": "string" + }, + "user_id": { + "type": "integer" + }, + "primary_group_id": { + "type": [ + "integer", + "null" + ] + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/t/{id}/posts.json": { + "get": { + "summary": "Get specific posts from a topic", + "tags": [ + "Topics" + ], + "operationId": "getSpecificPostsFromTopic", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "specific posts", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "post_stream": { + "type": "object", + "properties": { + "posts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "username": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "cooked": { + "type": "string" + }, + "post_number": { + "type": "integer" + }, + "post_type": { + "type": "integer" + }, + "updated_at": { + "type": "string" + }, + "reply_count": { + "type": "integer" + }, + "reply_to_post_number": { + "type": [ + "string", + "null" + ] + }, + "quote_count": { + "type": "integer" + }, + "incoming_link_count": { + "type": "integer" + }, + "reads": { + "type": "integer" + }, + "readers_count": { + "type": "integer" + }, + "score": { + "type": "number" + }, + "yours": { + "type": "boolean" + }, + "topic_id": { + "type": "integer" + }, + "topic_slug": { + "type": "string" + }, + "display_username": { + "type": [ + "string", + "null" + ] + }, + "primary_group_name": { + "type": [ + "string", + "null" + ] + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "version": { + "type": "integer" + }, + "can_edit": { + "type": "boolean" + }, + "can_delete": { + "type": "boolean" + }, + "can_recover": { + "type": "boolean" + }, + "can_wiki": { + "type": "boolean" + }, + "read": { + "type": "boolean" + }, + "user_title": { + "type": [ + "string", + "null" + ] + }, + "actions_summary": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "can_act": { + "type": "boolean" + } + } + } + }, + "moderator": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "staff": { + "type": "boolean" + }, + "user_id": { + "type": "integer" + }, + "hidden": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + }, + "deleted_at": { + "type": [ + "string", + "null" + ] + }, + "user_deleted": { + "type": "boolean" + }, + "edit_reason": { + "type": [ + "string", + "null" + ] + }, + "can_view_edit_history": { + "type": "boolean" + }, + "wiki": { + "type": "boolean" + }, + "reviewable_id": { + "type": "integer" + }, + "reviewable_score_count": { + "type": "integer" + }, + "reviewable_score_pending_count": { + "type": "integer" + } + } + } + } + } + }, + "id": { + "type": "integer" + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "post_ids[]": { + "type": "integer" + } + }, + "required": [ + "post_ids[]" + ] + } + } + } + } + } + }, + "/t/{id}.json": { + "get": { + "summary": "Get a single topic", + "tags": [ + "Topics" + ], + "operationId": "getTopic", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "specific posts", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "post_stream": { + "type": "object", + "additionalProperties": false, + "properties": { + "posts": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "username": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "cooked": { + "type": "string" + }, + "post_number": { + "type": "integer" + }, + "post_type": { + "type": "integer" + }, + "updated_at": { + "type": "string" + }, + "reply_count": { + "type": "integer" + }, + "reply_to_post_number": { + "type": [ + "string", + "null" + ] + }, + "quote_count": { + "type": "integer" + }, + "incoming_link_count": { + "type": "integer" + }, + "reads": { + "type": "integer" + }, + "readers_count": { + "type": "integer" + }, + "score": { + "type": "number" + }, + "yours": { + "type": "boolean" + }, + "topic_id": { + "type": "integer" + }, + "topic_slug": { + "type": "string" + }, + "display_username": { + "type": "string" + }, + "primary_group_name": { + "type": [ + "string", + "null" + ] + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "version": { + "type": "integer" + }, + "can_edit": { + "type": "boolean" + }, + "can_delete": { + "type": "boolean" + }, + "can_recover": { + "type": "boolean" + }, + "can_see_hidden_post": { + "type": "boolean" + }, + "can_wiki": { + "type": "boolean" + }, + "link_counts": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "url": { + "type": "string" + }, + "internal": { + "type": "boolean" + }, + "reflection": { + "type": "boolean" + }, + "title": { + "type": "string" + }, + "clicks": { + "type": "integer" + } + }, + "required": [ + "url", + "internal", + "reflection", + "title", + "clicks" + ] + } + }, + "read": { + "type": "boolean" + }, + "user_title": { + "type": [ + "string", + "null" + ] + }, + "bookmarked": { + "type": "boolean" + }, + "actions_summary": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "can_act": { + "type": "boolean" + } + }, + "required": [ + "id", + "can_act" + ] + } + }, + "moderator": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "staff": { + "type": "boolean" + }, + "user_id": { + "type": "integer" + }, + "hidden": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + }, + "deleted_at": { + "type": [ + "string", + "null" + ] + }, + "user_deleted": { + "type": "boolean" + }, + "edit_reason": { + "type": [ + "string", + "null" + ] + }, + "can_view_edit_history": { + "type": "boolean" + }, + "wiki": { + "type": "boolean" + }, + "reviewable_id": { + "type": "integer" + }, + "reviewable_score_count": { + "type": "integer" + }, + "reviewable_score_pending_count": { + "type": "integer" + } + }, + "required": [ + "id", + "name", + "username", + "avatar_template", + "created_at", + "cooked", + "post_number", + "post_type", + "updated_at", + "reply_count", + "reply_to_post_number", + "quote_count", + "incoming_link_count", + "reads", + "readers_count", + "score", + "yours", + "topic_id", + "topic_slug", + "display_username", + "primary_group_name", + "flair_name", + "flair_url", + "flair_bg_color", + "flair_color", + "version", + "can_edit", + "can_delete", + "can_recover", + "can_wiki", + "link_counts", + "read", + "user_title", + "bookmarked", + "actions_summary", + "moderator", + "admin", + "staff", + "user_id", + "hidden", + "trust_level", + "deleted_at", + "user_deleted", + "edit_reason", + "can_view_edit_history", + "wiki", + "reviewable_id", + "reviewable_score_count", + "reviewable_score_pending_count" + ] + } + }, + "stream": { + "type": "array", + "items": {} + } + }, + "required": [ + "posts", + "stream" + ] + }, + "timeline_lookup": { + "type": "array", + "items": {} + }, + "suggested_topics": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "fancy_title": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "posts_count": { + "type": "integer" + }, + "reply_count": { + "type": "integer" + }, + "highest_post_number": { + "type": "integer" + }, + "image_url": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "last_posted_at": { + "type": [ + "string", + "null" + ] + }, + "bumped": { + "type": "boolean" + }, + "bumped_at": { + "type": "string" + }, + "archetype": { + "type": "string" + }, + "unseen": { + "type": "boolean" + }, + "pinned": { + "type": "boolean" + }, + "unpinned": { + "type": [ + "string", + "null" + ] + }, + "excerpt": { + "type": "string" + }, + "visible": { + "type": "boolean" + }, + "closed": { + "type": "boolean" + }, + "archived": { + "type": "boolean" + }, + "bookmarked": { + "type": [ + "string", + "null" + ] + }, + "liked": { + "type": [ + "string", + "null" + ] + }, + "tags": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "slug" + ] + } + }, + "tags_descriptions": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "like_count": { + "type": "integer" + }, + "views": { + "type": "integer" + }, + "category_id": { + "type": "integer" + }, + "featured_link": { + "type": [ + "string", + "null" + ] + }, + "posters": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "extras": { + "type": "string" + }, + "description": { + "type": "string" + }, + "user": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template" + ] + } + }, + "required": [ + "extras", + "description", + "user" + ] + } + } + }, + "required": [ + "id", + "title", + "fancy_title", + "slug", + "posts_count", + "reply_count", + "highest_post_number", + "image_url", + "created_at", + "last_posted_at", + "bumped", + "bumped_at", + "archetype", + "unseen", + "pinned", + "unpinned", + "excerpt", + "visible", + "closed", + "archived", + "bookmarked", + "liked", + "tags", + "tags_descriptions", + "like_count", + "views", + "category_id", + "featured_link", + "posters" + ] + } + }, + "tags": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "slug" + ] + } + }, + "tags_descriptions": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "fancy_title": { + "type": "string" + }, + "posts_count": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "views": { + "type": "integer" + }, + "reply_count": { + "type": "integer" + }, + "like_count": { + "type": "integer" + }, + "last_posted_at": { + "type": [ + "string", + "null" + ] + }, + "visible": { + "type": "boolean" + }, + "closed": { + "type": "boolean" + }, + "archived": { + "type": "boolean" + }, + "has_summary": { + "type": "boolean" + }, + "archetype": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "category_id": { + "type": "integer" + }, + "word_count": { + "type": [ + "integer", + "null" + ] + }, + "deleted_at": { + "type": [ + "string", + "null" + ] + }, + "user_id": { + "type": "integer" + }, + "featured_link": { + "type": [ + "string", + "null" + ] + }, + "pinned_globally": { + "type": "boolean" + }, + "pinned_at": { + "type": [ + "string", + "null" + ] + }, + "pinned_until": { + "type": [ + "string", + "null" + ] + }, + "image_url": { + "type": [ + "string", + "null" + ] + }, + "slow_mode_seconds": { + "type": "integer" + }, + "draft": { + "type": [ + "string", + "null" + ] + }, + "draft_key": { + "type": "string" + }, + "draft_sequence": { + "type": "integer" + }, + "unpinned": { + "type": [ + "string", + "null" + ] + }, + "pinned": { + "type": "boolean" + }, + "current_post_number": { + "type": "integer" + }, + "highest_post_number": { + "type": [ + "integer", + "null" + ] + }, + "deleted_by": { + "type": [ + "string", + "null" + ] + }, + "has_deleted": { + "type": "boolean" + }, + "actions_summary": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "count": { + "type": "integer" + }, + "hidden": { + "type": "boolean" + }, + "can_act": { + "type": "boolean" + } + }, + "required": [ + "id", + "count", + "hidden", + "can_act" + ] + } + }, + "chunk_size": { + "type": "integer" + }, + "bookmarked": { + "type": "boolean" + }, + "bookmarks": { + "type": "array", + "items": {} + }, + "topic_timer": { + "type": [ + "string", + "null" + ] + }, + "message_bus_last_id": { + "type": "integer" + }, + "participant_count": { + "type": "integer" + }, + "show_read_indicator": { + "type": "boolean" + }, + "thumbnails": { + "type": [ + "string", + "null" + ] + }, + "slow_mode_enabled_until": { + "type": [ + "string", + "null" + ] + }, + "details": { + "type": "object", + "additionalProperties": false, + "properties": { + "can_edit": { + "type": "boolean" + }, + "notification_level": { + "type": "integer" + }, + "can_move_posts": { + "type": "boolean" + }, + "can_delete": { + "type": "boolean" + }, + "can_remove_allowed_users": { + "type": "boolean" + }, + "can_create_post": { + "type": "boolean" + }, + "can_reply_as_new_topic": { + "type": "boolean" + }, + "can_invite_to": { + "type": "boolean" + }, + "can_invite_via_email": { + "type": "boolean" + }, + "can_flag_topic": { + "type": "boolean" + }, + "can_convert_topic": { + "type": "boolean" + }, + "can_review_topic": { + "type": "boolean" + }, + "can_close_topic": { + "type": "boolean" + }, + "can_archive_topic": { + "type": "boolean" + }, + "can_split_merge_topic": { + "type": "boolean" + }, + "can_edit_staff_notes": { + "type": "boolean" + }, + "can_toggle_topic_visibility": { + "type": "boolean" + }, + "can_pin_unpin_topic": { + "type": "boolean" + }, + "can_banner_topic": { + "type": "boolean" + }, + "can_moderate_category": { + "type": "boolean" + }, + "can_remove_self_id": { + "type": "integer" + }, + "participants": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "post_count": { + "type": "integer" + }, + "primary_group_name": { + "type": [ + "string", + "null" + ] + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_group_id": { + "type": [ + "integer", + "null" + ] + }, + "admin": { + "type": "boolean" + }, + "moderator": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "post_count", + "primary_group_name", + "flair_name", + "flair_url", + "flair_color", + "flair_bg_color", + "admin", + "moderator", + "trust_level" + ] + } + }, + "created_by": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template" + ] + }, + "last_poster": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template" + ] + } + }, + "required": [ + "can_edit", + "notification_level", + "can_move_posts", + "can_delete", + "can_remove_allowed_users", + "can_create_post", + "can_reply_as_new_topic", + "can_convert_topic", + "can_review_topic", + "can_close_topic", + "can_archive_topic", + "can_split_merge_topic", + "can_edit_staff_notes", + "can_toggle_topic_visibility", + "can_pin_unpin_topic", + "can_moderate_category", + "can_remove_self_id", + "created_by", + "last_poster" + ] + } + }, + "required": [ + "post_stream", + "timeline_lookup", + "suggested_topics", + "tags", + "tags_descriptions", + "id", + "title", + "fancy_title", + "posts_count", + "created_at", + "views", + "reply_count", + "like_count", + "last_posted_at", + "visible", + "closed", + "archived", + "has_summary", + "archetype", + "slug", + "category_id", + "word_count", + "deleted_at", + "user_id", + "featured_link", + "pinned_globally", + "pinned_at", + "pinned_until", + "image_url", + "slow_mode_seconds", + "draft", + "draft_key", + "draft_sequence", + "unpinned", + "pinned", + "highest_post_number", + "deleted_by", + "has_deleted", + "actions_summary", + "chunk_size", + "bookmarked", + "bookmarks", + "topic_timer", + "message_bus_last_id", + "participant_count", + "show_read_indicator", + "thumbnails", + "slow_mode_enabled_until", + "details" + ] + } + } + } + } + } + }, + "delete": { + "summary": "Remove a topic", + "tags": [ + "Topics" + ], + "operationId": "removeTopic", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "specific posts" + } + } + } + }, + "/t/-/{id}.json": { + "put": { + "summary": "Update a topic", + "tags": [ + "Topics" + ], + "operationId": "updateTopic", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "topic updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "basic_topic": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "fancy_title": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "posts_count": { + "type": "integer" + } + } + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "category_id": { + "type": "integer" + } + } + } + } + } + } + } + } + } + }, + "/t/{id}/invite.json": { + "post": { + "summary": "Invite to topic", + "tags": [ + "Topics", + "Invites" + ], + "operationId": "inviteToTopic", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "topic updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "user": { + "type": "string" + }, + "email": { + "type": "string" + } + } + } + } + } + } + } + }, + "/t/{id}/invite-group.json": { + "post": { + "summary": "Invite group to topic", + "tags": [ + "Topics", + "Invites" + ], + "operationId": "inviteGroupToTopic", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "invites to a PM", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "group": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "group": { + "type": "string", + "description": "The name of the group to invite" + }, + "should_notify": { + "type": "boolean", + "description": "Whether to notify the group, it defaults to true" + } + } + } + } + } + } + } + }, + "/t/{id}/bookmark.json": { + "put": { + "summary": "Bookmark topic", + "tags": [ + "Topics" + ], + "operationId": "bookmarkTopic", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "topic updated" + } + } + } + }, + "/t/{id}/status.json": { + "put": { + "summary": "Update the status of a topic", + "tags": [ + "Topics" + ], + "operationId": "updateTopicStatus", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "topic updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "string", + "example": "OK" + }, + "topic_status_update": { + "type": [ + "string", + "null" + ] + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "closed", + "pinned", + "pinned_globally", + "archived", + "visible" + ] + }, + "enabled": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "until": { + "type": "string", + "description": "Only required for `pinned` and `pinned_globally`", + "example": "2030-12-31" + } + }, + "required": [ + "status", + "enabled" + ] + } + } + } + } + } + }, + "/latest.json": { + "get": { + "summary": "Get the latest topics", + "tags": [ + "Topics" + ], + "operationId": "listLatestTopics", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "order", + "in": "query", + "description": "Enum: `default`, `created`, `activity`, `views`, `posts`, `category`,\n`likes`, `op_likes`, `posters`", + "schema": { + "type": "string" + } + }, + { + "name": "ascending", + "in": "query", + "description": "Defaults to `desc`, add `ascending=true` to sort asc", + "schema": { + "type": "string" + } + }, + { + "name": "per_page", + "in": "query", + "description": "Maximum number of topics returned, between 1-100", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "topic updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + } + } + } + }, + "primary_groups": { + "type": "array", + "items": {} + }, + "topic_list": { + "type": "object", + "properties": { + "can_create_topic": { + "type": "boolean" + }, + "draft": { + "type": [ + "string", + "null" + ] + }, + "draft_key": { + "type": "string" + }, + "draft_sequence": { + "type": "integer" + }, + "per_page": { + "type": "integer" + }, + "topics": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "fancy_title": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "posts_count": { + "type": "integer" + }, + "reply_count": { + "type": "integer" + }, + "highest_post_number": { + "type": "integer" + }, + "image_url": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "last_posted_at": { + "type": "string" + }, + "bumped": { + "type": "boolean" + }, + "bumped_at": { + "type": "string" + }, + "archetype": { + "type": "string" + }, + "unseen": { + "type": "boolean" + }, + "last_read_post_number": { + "type": "integer" + }, + "unread_posts": { + "type": "integer" + }, + "pinned": { + "type": "boolean" + }, + "unpinned": { + "type": [ + "string", + "null" + ] + }, + "visible": { + "type": "boolean" + }, + "closed": { + "type": "boolean" + }, + "archived": { + "type": "boolean" + }, + "notification_level": { + "type": "integer" + }, + "bookmarked": { + "type": "boolean" + }, + "liked": { + "type": "boolean" + }, + "views": { + "type": "integer" + }, + "like_count": { + "type": "integer" + }, + "has_summary": { + "type": "boolean" + }, + "last_poster_username": { + "type": "string" + }, + "category_id": { + "type": "integer" + }, + "op_like_count": { + "type": "integer" + }, + "pinned_globally": { + "type": "boolean" + }, + "featured_link": { + "type": [ + "string", + "null" + ] + }, + "posters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "extras": { + "type": "string" + }, + "description": { + "type": "string" + }, + "user_id": { + "type": "integer" + }, + "primary_group_id": { + "type": [ + "integer", + "null" + ] + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/top.json": { + "get": { + "summary": "Get the top topics filtered by period", + "tags": [ + "Topics" + ], + "operationId": "listTopTopics", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "period", + "in": "query", + "description": "Enum: `all`, `yearly`, `quarterly`, `monthly`, `weekly`, `daily`", + "schema": { + "type": "string" + } + }, + { + "name": "per_page", + "in": "query", + "description": "Maximum number of topics returned, between 1-100", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + } + } + }, + "primary_groups": { + "type": "array", + "items": {} + }, + "topic_list": { + "type": "object", + "properties": { + "can_create_topic": { + "type": "boolean" + }, + "draft": { + "type": [ + "string", + "null" + ] + }, + "draft_key": { + "type": "string" + }, + "draft_sequence": { + "type": "integer" + }, + "for_period": { + "type": "string" + }, + "per_page": { + "type": "integer" + }, + "topics": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "fancy_title": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "posts_count": { + "type": "integer" + }, + "reply_count": { + "type": "integer" + }, + "highest_post_number": { + "type": "integer" + }, + "image_url": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "last_posted_at": { + "type": "string" + }, + "bumped": { + "type": "boolean" + }, + "bumped_at": { + "type": "string" + }, + "archetype": { + "type": "string" + }, + "unseen": { + "type": "boolean" + }, + "last_read_post_number": { + "type": "integer" + }, + "unread_posts": { + "type": "integer" + }, + "pinned": { + "type": "boolean" + }, + "unpinned": { + "type": "boolean" + }, + "visible": { + "type": "boolean" + }, + "closed": { + "type": "boolean" + }, + "archived": { + "type": "boolean" + }, + "notification_level": { + "type": "integer" + }, + "bookmarked": { + "type": "boolean" + }, + "liked": { + "type": "boolean" + }, + "views": { + "type": "integer" + }, + "like_count": { + "type": "integer" + }, + "has_summary": { + "type": "boolean" + }, + "last_poster_username": { + "type": "string" + }, + "category_id": { + "type": "integer" + }, + "op_like_count": { + "type": "integer" + }, + "pinned_globally": { + "type": "boolean" + }, + "featured_link": { + "type": [ + "string", + "null" + ] + }, + "posters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "extras": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": "string" + }, + "user_id": { + "type": "integer" + }, + "primary_group_id": { + "type": [ + "integer", + "null" + ] + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/t/{id}/notifications.json": { + "post": { + "summary": "Set notification level", + "tags": [ + "Topics" + ], + "operationId": "setNotificationLevel", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "topic updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "string", + "example": "OK" + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "notification_level": { + "type": "string", + "enum": [ + "0", + "1", + "2", + "3" + ] + } + }, + "required": [ + "notification_level" + ] + } + } + } + } + } + }, + "/t/{id}/change-timestamp.json": { + "put": { + "summary": "Update topic timestamp", + "tags": [ + "Topics" + ], + "operationId": "updateTopicTimestamp", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "topic updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "string", + "example": "OK" + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "timestamp": { + "type": "string", + "example": "1594291380" + } + }, + "required": [ + "timestamp" + ] + } + } + } + } + } + }, + "/t/{id}/timer.json": { + "post": { + "summary": "Create topic timer", + "tags": [ + "Topics" + ], + "operationId": "createTopicTimer", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "topic updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "string", + "example": "OK" + }, + "execute_at": { + "type": "string" + }, + "duration": { + "type": [ + "string", + "null" + ] + }, + "based_on_last_post": { + "type": "boolean" + }, + "closed": { + "type": "boolean" + }, + "category_id": { + "type": [ + "integer", + "null" + ] + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "time": { + "type": "string", + "example": "" + }, + "status_type": { + "type": "string" + }, + "based_on_last_post": { + "type": "boolean" + }, + "category_id": { + "type": "integer" + } + } + } + } + } + } + } + }, + "/t/external_id/{external_id}.json": { + "get": { + "summary": "Get topic by external_id", + "tags": [ + "Topics" + ], + "operationId": "getTopicByExternalId", + "parameters": [ + { + "name": "external_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "301": { + "description": "redirects to /t/{topic_id}.json" + } + } + } + }, + "/uploads.json": { + "post": { + "summary": "Creates an upload", + "tags": [ + "Uploads" + ], + "operationId": "createUpload", + "parameters": [], + "responses": { + "200": { + "description": "file uploaded", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "original_filename": { + "type": "string" + }, + "filesize": { + "type": "integer" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "thumbnail_width": { + "type": "integer" + }, + "thumbnail_height": { + "type": "integer" + }, + "extension": { + "type": "string" + }, + "short_url": { + "type": "string" + }, + "short_path": { + "type": "string" + }, + "retain_hours": { + "type": [ + "string", + "null" + ] + }, + "human_filesize": { + "type": "string" + }, + "dominant_color": { + "type": [ + "string", + "null" + ] + }, + "thumbnail": { + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "upload_id": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "extension": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "filesize": { + "type": "integer" + } + } + }, + "optimized_video": { + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "upload_id": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "extension": { + "type": "string" + }, + "filesize": { + "type": "integer" + }, + "sha1": { + "type": "string" + }, + "original_filename": { + "type": "string" + } + } + } + }, + "required": [ + "id", + "url", + "original_filename", + "filesize", + "width", + "height", + "thumbnail_width", + "thumbnail_height", + "extension", + "short_url", + "short_path", + "retain_hours", + "human_filesize" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "avatar", + "profile_background", + "card_background", + "custom_emoji", + "composer" + ] + }, + "user_id": { + "type": "integer", + "description": "required if uploading an avatar" + }, + "synchronous": { + "type": "boolean", + "description": "Use this flag to return an id and url" + }, + "file": { + "type": "string", + "format": "binary" + } + }, + "required": [ + "type" + ] + } + } + } + } + } + }, + "/uploads/generate-presigned-put.json": { + "post": { + "summary": "Initiates a direct external upload", + "tags": [ + "Uploads" + ], + "operationId": "generatePresignedPut", + "description": "Direct external uploads bypass the usual method of creating uploads\nvia the POST /uploads route, and upload directly to an external provider,\nwhich by default is S3. This route begins the process, and will return\na unique identifier for the external upload as well as a presigned URL\nwhich is where the file binary blob should be uploaded to.\n\nOnce the upload is complete to the external service, you must call the\nPOST /complete-external-upload route using the unique identifier returned\nby this route, which will create any required Upload record in the Discourse\ndatabase and also move file from its temporary location to the final\ndestination in the external storage service.\n\nYou must have the correct permissions and CORS settings configured in your\nexternal provider. We support AWS S3 as the default. See:\n\nhttps://meta.discourse.org/t/-/210469#s3-multipart-direct-uploads-4.\n\nAn external file store must be set up and `enable_direct_s3_uploads` must\nbe set to true for this endpoint to function.\n\n", + "parameters": [], + "responses": { + "200": { + "description": "external upload initialized", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "key": { + "type": "string", + "description": "The path of the temporary file on the external storage\nservice.", + "example": "temp/site/uploads/default/12345/67890.jpg" + }, + "url": { + "type": "string", + "description": "A presigned PUT URL which must be used to upload\nthe file binary blob to.", + "example": "https://file-uploads.s3.us-west-2.amazonaws.com/temp/site/uploads/default/123/456.jpg?x-amz-acl=private&x-amz-meta-sha1-checksum=sha1&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AAAAus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20211221T011246Z&X-Amz-Expires=600&X-Amz-SignedHeaders=host&X-Amz-Signature=12345678" + }, + "signed_headers": { + "type": "object", + "description": "A map of headers that must be sent with the PUT request.", + "example": { + "x-amz-acl": "private", + "x-amz-meta-sha1-checksum": "sha1" + } + }, + "unique_identifier": { + "type": "string", + "description": "A unique string that identifies the external upload.\nThis must be stored and then sent in the /complete-external-upload\nendpoint to complete the direct upload.", + "example": "66e86218-80d9-4bda-b4d5-2b6def968705" + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "avatar", + "profile_background", + "card_background", + "custom_emoji", + "composer" + ] + }, + "file_name": { + "type": "string", + "example": "IMG_2021.jpeg" + }, + "file_size": { + "type": "integer", + "description": "File size should be represented in bytes.", + "example": 4096 + }, + "metadata": { + "type": "object", + "additionalProperties": false, + "properties": { + "sha1-checksum": { + "type": "string", + "description": "The SHA1 checksum of the upload binary blob. Optionally\nbe provided and serves as an additional security check when\nlater processing the file in complete-external-upload endpoint." + } + } + } + }, + "required": [ + "type", + "file_name", + "file_size" + ] + } + } + } + } + } + }, + "/uploads/complete-external-upload.json": { + "post": { + "summary": "Completes a direct external upload", + "tags": [ + "Uploads" + ], + "operationId": "completeExternalUpload", + "description": "Completes an external upload initialized with /get-presigned-put. The\nfile will be moved from its temporary location in external storage to\na final destination in the S3 bucket. An Upload record will also be\ncreated in the database in most cases.\n\nIf a sha1-checksum was provided in the initial request it will also\nbe compared with the uploaded file in storage to make sure the same\nfile was uploaded. The file size will be compared for the same reason.\n\nYou must have the correct permissions and CORS settings configured in your\nexternal provider. We support AWS S3 as the default. See:\n\nhttps://meta.discourse.org/t/-/210469#s3-multipart-direct-uploads-4.\n\nAn external file store must be set up and `enable_direct_s3_uploads` must\nbe set to true for this endpoint to function.\n\n", + "parameters": [], + "responses": { + "200": { + "description": "external upload initialized", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "original_filename": { + "type": "string" + }, + "filesize": { + "type": "integer" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "thumbnail_width": { + "type": "integer" + }, + "thumbnail_height": { + "type": "integer" + }, + "extension": { + "type": "string" + }, + "short_url": { + "type": "string" + }, + "short_path": { + "type": "string" + }, + "retain_hours": { + "type": [ + "string", + "null" + ] + }, + "human_filesize": { + "type": "string" + }, + "dominant_color": { + "type": [ + "string", + "null" + ] + }, + "thumbnail": { + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "upload_id": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "extension": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "filesize": { + "type": "integer" + } + } + }, + "optimized_video": { + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "upload_id": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "extension": { + "type": "string" + }, + "filesize": { + "type": "integer" + }, + "sha1": { + "type": "string" + }, + "original_filename": { + "type": "string" + } + } + } + }, + "required": [ + "id", + "url", + "original_filename", + "filesize", + "width", + "height", + "thumbnail_width", + "thumbnail_height", + "extension", + "short_url", + "short_path", + "retain_hours", + "human_filesize" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "unique_identifier": { + "type": "string", + "example": "66e86218-80d9-4bda-b4d5-2b6def968705", + "description": "The unique identifier returned in the original /generate-presigned-put\nrequest." + }, + "for_private_message": { + "type": "string", + "example": "true", + "description": "Optionally set this to true if the upload is for a\nprivate message." + }, + "for_site_setting": { + "type": "string", + "example": "true", + "description": "Optionally set this to true if the upload is for a\nsite setting." + }, + "pasted": { + "type": "string", + "example": "true", + "description": "Optionally set this to true if the upload was pasted\ninto the upload area. This will convert PNG files to JPEG." + } + }, + "required": [ + "unique_identifier" + ] + } + } + } + } + } + }, + "/uploads/create-multipart.json": { + "post": { + "summary": "Creates a multipart external upload", + "tags": [ + "Uploads" + ], + "operationId": "createMultipartUpload", + "description": "Creates a multipart upload in the external storage provider, storing\na temporary reference to the external upload similar to /get-presigned-put.\n\nYou must have the correct permissions and CORS settings configured in your\nexternal provider. We support AWS S3 as the default. See:\n\nhttps://meta.discourse.org/t/-/210469#s3-multipart-direct-uploads-4.\n\nAn external file store must be set up and `enable_direct_s3_uploads` must\nbe set to true for this endpoint to function.\n\n", + "parameters": [], + "responses": { + "200": { + "description": "external upload initialized", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "key": { + "type": "string", + "description": "The path of the temporary file on the external storage\nservice.", + "example": "temp/site/uploads/default/12345/67890.jpg" + }, + "external_upload_identifier": { + "type": "string", + "description": "The identifier of the multipart upload in the external\nstorage provider. This is the multipart upload_id in AWS S3.", + "example": "84x83tmxy398t3y._Q_z8CoJYVr69bE6D7f8J6Oo0434QquLFoYdGVerWFx9X5HDEI_TP_95c34n853495x35345394.d.ghQ" + }, + "unique_identifier": { + "type": "string", + "description": "A unique string that identifies the external upload.\nThis must be stored and then sent in the /complete-multipart\nand /batch-presign-multipart-parts endpoints.", + "example": "66e86218-80d9-4bda-b4d5-2b6def968705" + } + }, + "required": [ + "external_upload_identifier", + "key", + "unique_identifier" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "upload_type": { + "type": "string", + "enum": [ + "avatar", + "profile_background", + "card_background", + "custom_emoji", + "composer" + ] + }, + "file_name": { + "type": "string", + "example": "IMG_2021.jpeg" + }, + "file_size": { + "type": "integer", + "description": "File size should be represented in bytes.", + "example": 4096 + }, + "metadata": { + "type": "object", + "additionalProperties": false, + "properties": { + "sha1-checksum": { + "type": "string", + "description": "The SHA1 checksum of the upload binary blob. Optionally\nbe provided and serves as an additional security check when\nlater processing the file in complete-external-upload endpoint." + } + } + } + }, + "required": [ + "upload_type", + "file_name", + "file_size" + ] + } + } + } + } + } + }, + "/uploads/batch-presign-multipart-parts.json": { + "post": { + "summary": "Generates batches of presigned URLs for multipart parts", + "tags": [ + "Uploads" + ], + "operationId": "batchPresignMultipartParts", + "description": "Multipart uploads are uploaded in chunks or parts to individual presigned\nURLs, similar to the one generated by /generate-presigned-put. The part\nnumbers provided must be between 1 and 10000. The total number of parts\nwill depend on the chunk size in bytes that you intend to use to upload\neach chunk. For example a 12MB file may have 2 5MB chunks and a final\n2MB chunk, for part numbers 1, 2, and 3.\n\nThis endpoint will return a presigned URL for each part number provided,\nwhich you can then use to send PUT requests for the binary chunk corresponding\nto that part. When the part is uploaded, the provider should return an\nETag for the part, and this should be stored along with the part number,\nbecause this is needed to complete the multipart upload.\n\nYou must have the correct permissions and CORS settings configured in your\nexternal provider. We support AWS S3 as the default. See:\n\nhttps://meta.discourse.org/t/-/210469#s3-multipart-direct-uploads-4.\n\nAn external file store must be set up and `enable_direct_s3_uploads` must\nbe set to true for this endpoint to function.\n\n", + "parameters": [], + "responses": { + "200": { + "description": "external upload initialized", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "presigned_urls": { + "type": "object", + "description": "The presigned URLs for each part number, which has\nthe part numbers as keys.", + "example": { + "1": "https://discourse-martin-uploads-test.s3.us-east-2.amazonaws.com/temp/uploads/default/123abc/123abc.jpg?partNumber=1&uploadId=123456abcd&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=test&X-Amz-Date=20211222T012336Z&X-Amz-Expires=600&X-Amz-SignedHeaders=host&X-Amz-Signature=abc123" + } + } + }, + "required": [ + "presigned_urls" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "part_numbers": { + "type": "array", + "description": "The part numbers to generate the presigned URLs for,\nmust be between 1 and 10000.", + "example": [ + 1, + 2, + 3 + ] + }, + "unique_identifier": { + "type": "string", + "description": "The unique identifier returned in the original /create-multipart\nrequest.", + "example": "66e86218-80d9-4bda-b4d5-2b6def968705" + } + }, + "required": [ + "part_numbers", + "unique_identifier" + ] + } + } + } + } + } + }, + "/uploads/abort-multipart.json": { + "post": { + "summary": "Abort multipart upload", + "tags": [ + "Uploads" + ], + "operationId": "abortMultipart", + "description": "This endpoint aborts the multipart upload initiated with /create-multipart.\nThis should be used when cancelling the upload. It does not matter if parts\nwere already uploaded into the external storage provider.\n\nYou must have the correct permissions and CORS settings configured in your\nexternal provider. We support AWS S3 as the default. See:\n\nhttps://meta.discourse.org/t/-/210469#s3-multipart-direct-uploads-4.\n\nAn external file store must be set up and `enable_direct_s3_uploads` must\nbe set to true for this endpoint to function.\n\n", + "parameters": [], + "responses": { + "200": { + "description": "external upload initialized", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string", + "example": "OK" + } + }, + "required": [ + "success" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "external_upload_identifier": { + "type": "string", + "description": "The identifier of the multipart upload in the external\nstorage provider. This is the multipart upload_id in AWS S3.", + "example": "84x83tmxy398t3y._Q_z8CoJYVr69bE6D7f8J6Oo0434QquLFoYdGVerWFx9X5HDEI_TP_95c34n853495x35345394.d.ghQ" + } + }, + "required": [ + "external_upload_identifier" + ] + } + } + } + } + } + }, + "/uploads/complete-multipart.json": { + "post": { + "summary": "Complete multipart upload", + "tags": [ + "Uploads" + ], + "operationId": "completeMultipart", + "description": "Completes the multipart upload in the external store, and copies the\nfile from its temporary location to its final location in the store.\nAll of the parts must have been uploaded to the external storage provider.\nAn Upload record will be completed in most cases once the file is copied\nto its final location.\n\nYou must have the correct permissions and CORS settings configured in your\nexternal provider. We support AWS S3 as the default. See:\n\nhttps://meta.discourse.org/t/-/210469#s3-multipart-direct-uploads-4.\n\nAn external file store must be set up and `enable_direct_s3_uploads` must\nbe set to true for this endpoint to function.\n\n", + "parameters": [], + "responses": { + "200": { + "description": "external upload initialized", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "original_filename": { + "type": "string" + }, + "filesize": { + "type": "integer" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "thumbnail_width": { + "type": "integer" + }, + "thumbnail_height": { + "type": "integer" + }, + "extension": { + "type": "string" + }, + "short_url": { + "type": "string" + }, + "short_path": { + "type": "string" + }, + "retain_hours": { + "type": [ + "string", + "null" + ] + }, + "human_filesize": { + "type": "string" + }, + "dominant_color": { + "type": [ + "string", + "null" + ] + }, + "thumbnail": { + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "upload_id": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "extension": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "filesize": { + "type": "integer" + } + } + }, + "optimized_video": { + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "upload_id": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "extension": { + "type": "string" + }, + "filesize": { + "type": "integer" + }, + "sha1": { + "type": "string" + }, + "original_filename": { + "type": "string" + } + } + } + }, + "required": [ + "id", + "url", + "original_filename", + "filesize", + "width", + "height", + "thumbnail_width", + "thumbnail_height", + "extension", + "short_url", + "short_path", + "retain_hours", + "human_filesize" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "unique_identifier": { + "type": "string", + "example": "66e86218-80d9-4bda-b4d5-2b6def968705", + "description": "The unique identifier returned in the original /create-multipart\nrequest." + }, + "parts": { + "type": "array", + "example": [ + { + "part_number": 1, + "etag": "0c376dcfcc2606f4335bbc732de93344" + }, + { + "part_number": 2, + "etag": "09ert8cfcc2606f4335bbc732de91122" + } + ], + "description": "All of the part numbers and their corresponding ETags\nthat have been uploaded must be provided." + } + }, + "required": [ + "unique_identifier", + "parts" + ] + } + } + } + } + } + }, + "/user-badges/{username}.json": { + "get": { + "summary": "List badges for a user", + "tags": [ + "Badges", + "Users" + ], + "operationId": "listUserBadges", + "parameters": [ + { + "name": "username", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "badges": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "grant_count": { + "type": "integer" + }, + "allow_title": { + "type": "boolean" + }, + "multiple_grant": { + "type": "boolean" + }, + "icon": { + "type": "string" + }, + "image_url": { + "type": [ + "string", + "null" + ] + }, + "listable": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "badge_grouping_id": { + "type": "integer" + }, + "system": { + "type": "boolean" + }, + "slug": { + "type": "string" + }, + "manually_grantable": { + "type": "boolean" + }, + "badge_type_id": { + "type": "integer" + } + }, + "required": [ + "id", + "name", + "description", + "grant_count", + "allow_title", + "multiple_grant", + "icon", + "image_url", + "listable", + "enabled", + "badge_grouping_id", + "system", + "slug", + "manually_grantable", + "badge_type_id" + ] + } + }, + "badge_types": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "sort_order": { + "type": "integer" + } + }, + "required": [ + "id", + "name", + "sort_order" + ] + } + }, + "granted_bies": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "admin": { + "type": "boolean" + }, + "moderator": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "flair_name", + "admin", + "moderator", + "trust_level" + ] + } + }, + "user_badges": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "granted_at": { + "type": "string" + }, + "grouping_position": { + "type": "integer" + }, + "is_favorite": { + "type": [ + "string", + "null" + ] + }, + "can_favorite": { + "type": "boolean" + }, + "badge_id": { + "type": "integer" + }, + "granted_by_id": { + "type": "integer" + } + }, + "required": [ + "id", + "granted_at", + "grouping_position", + "is_favorite", + "can_favorite", + "badge_id", + "granted_by_id" + ] + } + } + }, + "required": [ + "user_badges" + ] + } + } + } + } + } + } + }, + "/users.json": { + "post": { + "summary": "Creates a user", + "tags": [ + "Users" + ], + "operationId": "createUser", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "user created", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "boolean" + }, + "active": { + "type": "boolean" + }, + "message": { + "type": "string" + }, + "user_id": { + "type": "integer" + } + }, + "required": [ + "success", + "active", + "message" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "username": { + "type": "string" + }, + "active": { + "type": "boolean", + "description": "This param requires an admin api key in the request\nheader or it will be ignored" + }, + "approved": { + "type": "boolean" + }, + "user_fields": { + "type": "object", + "additionalProperties": true, + "properties": { + "1": { + "type": "boolean" + } + } + }, + "external_ids": { + "type": "object" + } + }, + "required": [ + "name", + "email", + "password", + "username" + ] + } + } + } + } + } + }, + "/u/{username}.json": { + "get": { + "summary": "Get a single user by username", + "tags": [ + "Users" + ], + "operationId": "getUser", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "user with primary group response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "user_badges": { + "type": "array", + "items": {} + }, + "user": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "last_posted_at": { + "type": [ + "string", + "null" + ] + }, + "last_seen_at": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "ignored": { + "type": "boolean" + }, + "muted": { + "type": "boolean" + }, + "can_ignore_user": { + "type": "boolean" + }, + "can_ignore_users": { + "type": "boolean" + }, + "can_mute_user": { + "type": "boolean" + }, + "can_mute_users": { + "type": "boolean" + }, + "can_send_private_messages": { + "type": "boolean" + }, + "can_send_private_message_to_user": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + }, + "moderator": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "badge_count": { + "type": "integer" + }, + "second_factor_backup_enabled": { + "type": "boolean" + }, + "user_fields": { + "type": "object", + "additionalProperties": false, + "properties": { + "1": { + "type": [ + "string", + "null" + ] + }, + "2": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "1", + "2" + ] + }, + "custom_fields": { + "type": "object", + "additionalProperties": false, + "properties": { + "first_name": { + "type": [ + "string", + "null" + ] + } + } + }, + "time_read": { + "type": "integer" + }, + "recent_time_read": { + "type": "integer" + }, + "primary_group_id": { + "type": [ + "integer", + "null" + ] + }, + "primary_group_name": { + "type": [ + "string", + "null" + ] + }, + "flair_group_id": { + "type": [ + "integer", + "null" + ] + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "featured_topic": { + "type": [ + "string", + "null" + ] + }, + "staged": { + "type": "boolean" + }, + "can_edit": { + "type": "boolean" + }, + "can_edit_username": { + "type": "boolean" + }, + "can_edit_email": { + "type": "boolean" + }, + "can_edit_name": { + "type": "boolean" + }, + "uploaded_avatar_id": { + "type": [ + "integer", + "null" + ] + }, + "has_title_badges": { + "type": "boolean" + }, + "pending_count": { + "type": "integer" + }, + "pending_posts_count": { + "type": "integer" + }, + "profile_view_count": { + "type": "integer" + }, + "second_factor_enabled": { + "type": "boolean" + }, + "can_upload_profile_header": { + "type": "boolean" + }, + "can_upload_user_card_background": { + "type": "boolean" + }, + "post_count": { + "type": "integer" + }, + "topic_count": { + "type": "integer" + }, + "can_be_deleted": { + "type": "boolean" + }, + "can_delete_all_posts": { + "type": "boolean" + }, + "locale": { + "type": [ + "string", + "null" + ] + }, + "muted_category_ids": { + "type": "array", + "items": {} + }, + "regular_category_ids": { + "type": "array", + "items": {} + }, + "watched_tags": { + "type": "array", + "items": {} + }, + "watching_first_post_tags": { + "type": "array", + "items": {} + }, + "tracked_tags": { + "type": "array", + "items": {} + }, + "muted_tags": { + "type": "array", + "items": {} + }, + "tracked_category_ids": { + "type": "array", + "items": {} + }, + "watched_category_ids": { + "type": "array", + "items": {} + }, + "watched_first_post_category_ids": { + "type": "array", + "items": {} + }, + "system_avatar_upload_id": { + "type": [ + "string", + "null" + ] + }, + "system_avatar_template": { + "type": "string" + }, + "muted_usernames": { + "type": "array", + "items": {} + }, + "ignored_usernames": { + "type": "array", + "items": {} + }, + "allowed_pm_usernames": { + "type": "array", + "items": {} + }, + "mailing_list_posts_per_day": { + "type": "integer" + }, + "can_change_bio": { + "type": "boolean" + }, + "can_change_location": { + "type": "boolean" + }, + "can_change_website": { + "type": "boolean" + }, + "can_change_tracking_preferences": { + "type": "boolean" + }, + "user_api_keys": { + "type": [ + "string", + "null" + ] + }, + "user_passkeys": { + "type": "array" + }, + "sidebar_tags": { + "type": "array" + }, + "sidebar_category_ids": { + "type": "array" + }, + "display_sidebar_tags": { + "type": "boolean" + }, + "can_pick_theme_with_custom_homepage": { + "type": "boolean" + }, + "user_auth_tokens": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "client_ip": { + "type": "string" + }, + "location": { + "type": "string" + }, + "browser": { + "type": "string" + }, + "device": { + "type": "string" + }, + "os": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "seen_at": { + "type": "string" + }, + "is_active": { + "type": "boolean" + } + }, + "required": [ + "id", + "client_ip", + "location", + "browser", + "device", + "os", + "icon", + "created_at", + "seen_at", + "is_active" + ] + } + }, + "user_notification_schedule": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "day_0_start_time": { + "type": "integer" + }, + "day_0_end_time": { + "type": "integer" + }, + "day_1_start_time": { + "type": "integer" + }, + "day_1_end_time": { + "type": "integer" + }, + "day_2_start_time": { + "type": "integer" + }, + "day_2_end_time": { + "type": "integer" + }, + "day_3_start_time": { + "type": "integer" + }, + "day_3_end_time": { + "type": "integer" + }, + "day_4_start_time": { + "type": "integer" + }, + "day_4_end_time": { + "type": "integer" + }, + "day_5_start_time": { + "type": "integer" + }, + "day_5_end_time": { + "type": "integer" + }, + "day_6_start_time": { + "type": "integer" + }, + "day_6_end_time": { + "type": "integer" + } + }, + "required": [ + "enabled", + "day_0_start_time", + "day_0_end_time", + "day_1_start_time", + "day_1_end_time", + "day_2_start_time", + "day_2_end_time", + "day_3_start_time", + "day_3_end_time", + "day_4_start_time", + "day_4_end_time", + "day_5_start_time", + "day_5_end_time", + "day_6_start_time", + "day_6_end_time" + ] + }, + "use_logo_small_as_avatar": { + "type": "boolean" + }, + "featured_user_badge_ids": { + "type": "array", + "items": {} + }, + "invited_by": { + "type": [ + "string", + "null" + ] + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "automatic": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "user_count": { + "type": "integer" + }, + "mentionable_level": { + "type": "integer" + }, + "messageable_level": { + "type": "integer" + }, + "visibility_level": { + "type": "integer" + }, + "primary_group": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "grant_trust_level": { + "type": [ + "string", + "null" + ] + }, + "incoming_email": { + "type": [ + "string", + "null" + ] + }, + "has_messages": { + "type": "boolean" + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "bio_raw": { + "type": [ + "string", + "null" + ] + }, + "bio_cooked": { + "type": [ + "string", + "null" + ] + }, + "bio_excerpt": { + "type": [ + "string", + "null" + ] + }, + "public_admission": { + "type": "boolean" + }, + "public_exit": { + "type": "boolean" + }, + "allow_membership_requests": { + "type": "boolean" + }, + "full_name": { + "type": [ + "string", + "null" + ] + }, + "default_notification_level": { + "type": "integer" + }, + "membership_request_template": { + "type": [ + "string", + "null" + ] + }, + "members_visibility_level": { + "type": "integer" + }, + "can_see_members": { + "type": "boolean" + }, + "can_admin_group": { + "type": "boolean" + }, + "publish_read_state": { + "type": "boolean" + } + }, + "required": [ + "id", + "automatic", + "name", + "display_name", + "user_count", + "mentionable_level", + "messageable_level", + "visibility_level", + "primary_group", + "title", + "grant_trust_level", + "incoming_email", + "has_messages", + "flair_url", + "flair_bg_color", + "flair_color", + "bio_raw", + "bio_cooked", + "bio_excerpt", + "public_admission", + "public_exit", + "allow_membership_requests", + "full_name", + "default_notification_level", + "membership_request_template", + "members_visibility_level", + "can_see_members", + "can_admin_group", + "publish_read_state" + ] + } + }, + "group_users": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "group_id": { + "type": "integer" + }, + "user_id": { + "type": "integer" + }, + "notification_level": { + "type": "integer" + }, + "owner": { + "type": "boolean" + } + }, + "required": [ + "group_id", + "user_id", + "notification_level" + ] + } + }, + "user_option": { + "type": "object", + "additionalProperties": false, + "properties": { + "user_id": { + "type": "integer" + }, + "mailing_list_mode": { + "type": "boolean" + }, + "mailing_list_mode_frequency": { + "type": "integer" + }, + "email_digests": { + "type": "boolean" + }, + "email_level": { + "type": "integer" + }, + "email_messages_level": { + "type": "integer" + }, + "external_links_in_new_tab": { + "type": "boolean" + }, + "bookmark_auto_delete_preference": { + "type": "integer" + }, + "color_scheme_id": { + "type": [ + "string", + "null" + ] + }, + "dark_scheme_id": { + "type": [ + "string", + "null" + ] + }, + "dynamic_favicon": { + "type": "boolean" + }, + "enable_quoting": { + "type": "boolean" + }, + "enable_smart_lists": { + "type": "boolean" + }, + "enable_markdown_monospace_font": { + "type": "boolean" + }, + "enable_defer": { + "type": "boolean" + }, + "digest_after_minutes": { + "type": "integer" + }, + "automatically_unpin_topics": { + "type": "boolean" + }, + "auto_track_topics_after_msecs": { + "type": "integer" + }, + "notification_level_when_replying": { + "type": "integer" + }, + "new_topic_duration_minutes": { + "type": "integer" + }, + "email_previous_replies": { + "type": "integer" + }, + "email_in_reply_to": { + "type": "boolean" + }, + "like_notification_frequency": { + "type": "integer" + }, + "notify_on_linked_posts": { + "type": "boolean" + }, + "include_tl0_in_digests": { + "type": "boolean" + }, + "theme_ids": { + "type": "array", + "items": {} + }, + "theme_key_seq": { + "type": "integer" + }, + "allow_private_messages": { + "type": "boolean" + }, + "enable_allowed_pm_users": { + "type": "boolean" + }, + "homepage_id": { + "type": [ + "string", + "null" + ] + }, + "hide_profile_and_presence": { + "type": "boolean" + }, + "hide_profile": { + "type": "boolean" + }, + "hide_presence": { + "type": "boolean" + }, + "text_size": { + "type": "string" + }, + "text_size_seq": { + "type": "integer" + }, + "title_count_mode": { + "type": "string" + }, + "timezone": { + "type": [ + "string", + "null" + ] + }, + "skip_new_user_tips": { + "type": "boolean" + }, + "default_calendar": { + "type": "string" + }, + "oldest_search_log_date": { + "type": [ + "string", + "null" + ] + }, + "sidebar_link_to_filtered_list": { + "type": "boolean" + }, + "sidebar_show_count_of_new_items": { + "type": "boolean" + }, + "watched_precedence_over_muted": { + "type": [ + "boolean" + ] + }, + "seen_popups": { + "type": [ + "array", + "null" + ] + }, + "topics_unread_when_closed": { + "type": "boolean" + }, + "composition_mode": { + "type": "integer" + }, + "interface_color_mode": { + "type": "integer" + }, + "show_original_content": { + "type": "boolean" + } + }, + "required": [ + "user_id", + "mailing_list_mode", + "mailing_list_mode_frequency", + "email_digests", + "email_level", + "email_messages_level", + "external_links_in_new_tab", + "color_scheme_id", + "dark_scheme_id", + "dynamic_favicon", + "enable_quoting", + "enable_smart_lists", + "enable_markdown_monospace_font", + "enable_defer", + "digest_after_minutes", + "automatically_unpin_topics", + "auto_track_topics_after_msecs", + "notification_level_when_replying", + "new_topic_duration_minutes", + "email_previous_replies", + "email_in_reply_to", + "like_notification_frequency", + "notify_on_linked_posts", + "include_tl0_in_digests", + "theme_ids", + "theme_key_seq", + "allow_private_messages", + "enable_allowed_pm_users", + "homepage_id", + "hide_profile_and_presence", + "hide_profile", + "hide_presence", + "text_size", + "text_size_seq", + "title_count_mode", + "timezone", + "skip_new_user_tips", + "topics_unread_when_closed", + "interface_color_mode", + "show_original_content" + ] + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "last_posted_at", + "last_seen_at", + "created_at", + "ignored", + "muted", + "can_ignore_user", + "can_mute_user", + "can_send_private_messages", + "can_send_private_message_to_user", + "trust_level", + "moderator", + "admin", + "title", + "badge_count", + "custom_fields", + "time_read", + "recent_time_read", + "primary_group_id", + "primary_group_name", + "flair_group_id", + "flair_name", + "flair_url", + "flair_bg_color", + "flair_color", + "featured_topic", + "staged", + "can_edit", + "can_edit_username", + "can_edit_email", + "can_edit_name", + "uploaded_avatar_id", + "has_title_badges", + "pending_count", + "profile_view_count", + "second_factor_enabled", + "can_upload_profile_header", + "can_upload_user_card_background", + "post_count", + "topic_count", + "can_be_deleted", + "can_delete_all_posts", + "locale", + "muted_category_ids", + "regular_category_ids", + "watched_tags", + "watching_first_post_tags", + "tracked_tags", + "muted_tags", + "tracked_category_ids", + "watched_category_ids", + "watched_first_post_category_ids", + "system_avatar_upload_id", + "system_avatar_template", + "muted_usernames", + "ignored_usernames", + "allowed_pm_usernames", + "mailing_list_posts_per_day", + "can_change_bio", + "can_change_location", + "can_change_website", + "can_change_tracking_preferences", + "user_api_keys", + "user_auth_tokens", + "user_notification_schedule", + "use_logo_small_as_avatar", + "featured_user_badge_ids", + "invited_by", + "groups", + "group_users", + "user_option" + ] + } + }, + "required": [ + "user_badges", + "user" + ] + } + } + } + } + } + }, + "put": { + "summary": "Update a user", + "tags": [ + "Users" + ], + "operationId": "updateUser", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "user updated", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string" + }, + "user": { + "type": "object" + } + }, + "required": [ + "success", + "user" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "external_ids": { + "type": "object" + } + } + } + } + } + } + } + }, + "/u/by-external/{external_id}.json": { + "get": { + "summary": "Get a user by external_id", + "tags": [ + "Users" + ], + "operationId": "getUserExternalId", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "external_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "user response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "user_badges": { + "type": "array", + "items": {} + }, + "user": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "last_posted_at": { + "type": [ + "string", + "null" + ] + }, + "last_seen_at": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "ignored": { + "type": "boolean" + }, + "muted": { + "type": "boolean" + }, + "can_ignore_user": { + "type": "boolean" + }, + "can_ignore_users": { + "type": "boolean" + }, + "can_mute_user": { + "type": "boolean" + }, + "can_mute_users": { + "type": "boolean" + }, + "can_send_private_messages": { + "type": "boolean" + }, + "can_send_private_message_to_user": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + }, + "moderator": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "badge_count": { + "type": "integer" + }, + "second_factor_backup_enabled": { + "type": "boolean" + }, + "user_fields": { + "type": "object", + "additionalProperties": false, + "properties": { + "1": { + "type": [ + "string", + "null" + ] + }, + "2": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "1", + "2" + ] + }, + "custom_fields": { + "type": "object", + "additionalProperties": false, + "properties": { + "first_name": { + "type": [ + "string", + "null" + ] + } + } + }, + "time_read": { + "type": "integer" + }, + "recent_time_read": { + "type": "integer" + }, + "primary_group_id": { + "type": [ + "integer", + "null" + ] + }, + "primary_group_name": { + "type": [ + "string", + "null" + ] + }, + "flair_group_id": { + "type": [ + "integer", + "null" + ] + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "featured_topic": { + "type": [ + "string", + "null" + ] + }, + "staged": { + "type": "boolean" + }, + "can_edit": { + "type": "boolean" + }, + "can_edit_username": { + "type": "boolean" + }, + "can_edit_email": { + "type": "boolean" + }, + "can_edit_name": { + "type": "boolean" + }, + "uploaded_avatar_id": { + "type": [ + "integer", + "null" + ] + }, + "has_title_badges": { + "type": "boolean" + }, + "pending_count": { + "type": "integer" + }, + "pending_posts_count": { + "type": "integer" + }, + "profile_view_count": { + "type": "integer" + }, + "second_factor_enabled": { + "type": "boolean" + }, + "can_upload_profile_header": { + "type": "boolean" + }, + "can_upload_user_card_background": { + "type": "boolean" + }, + "post_count": { + "type": "integer" + }, + "topic_count": { + "type": "integer" + }, + "can_be_deleted": { + "type": "boolean" + }, + "can_delete_all_posts": { + "type": "boolean" + }, + "locale": { + "type": [ + "string", + "null" + ] + }, + "muted_category_ids": { + "type": "array", + "items": {} + }, + "regular_category_ids": { + "type": "array", + "items": {} + }, + "watched_tags": { + "type": "array", + "items": {} + }, + "watching_first_post_tags": { + "type": "array", + "items": {} + }, + "tracked_tags": { + "type": "array", + "items": {} + }, + "muted_tags": { + "type": "array", + "items": {} + }, + "tracked_category_ids": { + "type": "array", + "items": {} + }, + "watched_category_ids": { + "type": "array", + "items": {} + }, + "watched_first_post_category_ids": { + "type": "array", + "items": {} + }, + "system_avatar_upload_id": { + "type": [ + "string", + "null" + ] + }, + "system_avatar_template": { + "type": "string" + }, + "muted_usernames": { + "type": "array", + "items": {} + }, + "ignored_usernames": { + "type": "array", + "items": {} + }, + "allowed_pm_usernames": { + "type": "array", + "items": {} + }, + "mailing_list_posts_per_day": { + "type": "integer" + }, + "can_change_bio": { + "type": "boolean" + }, + "can_change_location": { + "type": "boolean" + }, + "can_change_website": { + "type": "boolean" + }, + "can_change_tracking_preferences": { + "type": "boolean" + }, + "user_api_keys": { + "type": [ + "string", + "null" + ] + }, + "user_passkeys": { + "type": "array" + }, + "sidebar_tags": { + "type": "array" + }, + "sidebar_category_ids": { + "type": "array" + }, + "display_sidebar_tags": { + "type": "boolean" + }, + "can_pick_theme_with_custom_homepage": { + "type": "boolean" + }, + "user_auth_tokens": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "client_ip": { + "type": "string" + }, + "location": { + "type": "string" + }, + "browser": { + "type": "string" + }, + "device": { + "type": "string" + }, + "os": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "seen_at": { + "type": "string" + }, + "is_active": { + "type": "boolean" + } + }, + "required": [ + "id", + "client_ip", + "location", + "browser", + "device", + "os", + "icon", + "created_at", + "seen_at", + "is_active" + ] + } + }, + "user_notification_schedule": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "day_0_start_time": { + "type": "integer" + }, + "day_0_end_time": { + "type": "integer" + }, + "day_1_start_time": { + "type": "integer" + }, + "day_1_end_time": { + "type": "integer" + }, + "day_2_start_time": { + "type": "integer" + }, + "day_2_end_time": { + "type": "integer" + }, + "day_3_start_time": { + "type": "integer" + }, + "day_3_end_time": { + "type": "integer" + }, + "day_4_start_time": { + "type": "integer" + }, + "day_4_end_time": { + "type": "integer" + }, + "day_5_start_time": { + "type": "integer" + }, + "day_5_end_time": { + "type": "integer" + }, + "day_6_start_time": { + "type": "integer" + }, + "day_6_end_time": { + "type": "integer" + } + }, + "required": [ + "enabled", + "day_0_start_time", + "day_0_end_time", + "day_1_start_time", + "day_1_end_time", + "day_2_start_time", + "day_2_end_time", + "day_3_start_time", + "day_3_end_time", + "day_4_start_time", + "day_4_end_time", + "day_5_start_time", + "day_5_end_time", + "day_6_start_time", + "day_6_end_time" + ] + }, + "use_logo_small_as_avatar": { + "type": "boolean" + }, + "featured_user_badge_ids": { + "type": "array", + "items": {} + }, + "invited_by": { + "type": [ + "string", + "null" + ] + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "automatic": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "user_count": { + "type": "integer" + }, + "mentionable_level": { + "type": "integer" + }, + "messageable_level": { + "type": "integer" + }, + "visibility_level": { + "type": "integer" + }, + "primary_group": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "grant_trust_level": { + "type": [ + "string", + "null" + ] + }, + "incoming_email": { + "type": [ + "string", + "null" + ] + }, + "has_messages": { + "type": "boolean" + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "bio_raw": { + "type": [ + "string", + "null" + ] + }, + "bio_cooked": { + "type": [ + "string", + "null" + ] + }, + "bio_excerpt": { + "type": [ + "string", + "null" + ] + }, + "public_admission": { + "type": "boolean" + }, + "public_exit": { + "type": "boolean" + }, + "allow_membership_requests": { + "type": "boolean" + }, + "full_name": { + "type": [ + "string", + "null" + ] + }, + "default_notification_level": { + "type": "integer" + }, + "membership_request_template": { + "type": [ + "string", + "null" + ] + }, + "members_visibility_level": { + "type": "integer" + }, + "can_see_members": { + "type": "boolean" + }, + "can_admin_group": { + "type": "boolean" + }, + "publish_read_state": { + "type": "boolean" + } + }, + "required": [ + "id", + "automatic", + "name", + "display_name", + "user_count", + "mentionable_level", + "messageable_level", + "visibility_level", + "primary_group", + "title", + "grant_trust_level", + "incoming_email", + "has_messages", + "flair_url", + "flair_bg_color", + "flair_color", + "bio_raw", + "bio_cooked", + "bio_excerpt", + "public_admission", + "public_exit", + "allow_membership_requests", + "full_name", + "default_notification_level", + "membership_request_template", + "members_visibility_level", + "can_see_members", + "can_admin_group", + "publish_read_state" + ] + } + }, + "group_users": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "group_id": { + "type": "integer" + }, + "user_id": { + "type": "integer" + }, + "notification_level": { + "type": "integer" + }, + "owner": { + "type": "boolean" + } + }, + "required": [ + "group_id", + "user_id", + "notification_level" + ] + } + }, + "user_option": { + "type": "object", + "additionalProperties": false, + "properties": { + "user_id": { + "type": "integer" + }, + "mailing_list_mode": { + "type": "boolean" + }, + "mailing_list_mode_frequency": { + "type": "integer" + }, + "email_digests": { + "type": "boolean" + }, + "email_level": { + "type": "integer" + }, + "email_messages_level": { + "type": "integer" + }, + "external_links_in_new_tab": { + "type": "boolean" + }, + "bookmark_auto_delete_preference": { + "type": "integer" + }, + "color_scheme_id": { + "type": [ + "string", + "null" + ] + }, + "dark_scheme_id": { + "type": [ + "string", + "null" + ] + }, + "dynamic_favicon": { + "type": "boolean" + }, + "enable_quoting": { + "type": "boolean" + }, + "enable_smart_lists": { + "type": "boolean" + }, + "enable_markdown_monospace_font": { + "type": "boolean" + }, + "enable_defer": { + "type": "boolean" + }, + "digest_after_minutes": { + "type": "integer" + }, + "automatically_unpin_topics": { + "type": "boolean" + }, + "auto_track_topics_after_msecs": { + "type": "integer" + }, + "notification_level_when_replying": { + "type": "integer" + }, + "new_topic_duration_minutes": { + "type": "integer" + }, + "email_previous_replies": { + "type": "integer" + }, + "email_in_reply_to": { + "type": "boolean" + }, + "like_notification_frequency": { + "type": "integer" + }, + "notify_on_linked_posts": { + "type": "boolean" + }, + "include_tl0_in_digests": { + "type": "boolean" + }, + "theme_ids": { + "type": "array", + "items": {} + }, + "theme_key_seq": { + "type": "integer" + }, + "allow_private_messages": { + "type": "boolean" + }, + "enable_allowed_pm_users": { + "type": "boolean" + }, + "homepage_id": { + "type": [ + "string", + "null" + ] + }, + "hide_profile_and_presence": { + "type": "boolean" + }, + "hide_profile": { + "type": "boolean" + }, + "hide_presence": { + "type": "boolean" + }, + "text_size": { + "type": "string" + }, + "text_size_seq": { + "type": "integer" + }, + "title_count_mode": { + "type": "string" + }, + "timezone": { + "type": [ + "string", + "null" + ] + }, + "skip_new_user_tips": { + "type": "boolean" + }, + "default_calendar": { + "type": "string" + }, + "oldest_search_log_date": { + "type": [ + "string", + "null" + ] + }, + "sidebar_link_to_filtered_list": { + "type": "boolean" + }, + "sidebar_show_count_of_new_items": { + "type": "boolean" + }, + "watched_precedence_over_muted": { + "type": [ + "boolean" + ] + }, + "seen_popups": { + "type": [ + "array", + "null" + ] + }, + "topics_unread_when_closed": { + "type": "boolean" + }, + "composition_mode": { + "type": "integer" + }, + "interface_color_mode": { + "type": "integer" + }, + "show_original_content": { + "type": "boolean" + } + }, + "required": [ + "user_id", + "mailing_list_mode", + "mailing_list_mode_frequency", + "email_digests", + "email_level", + "email_messages_level", + "external_links_in_new_tab", + "color_scheme_id", + "dark_scheme_id", + "dynamic_favicon", + "enable_quoting", + "enable_smart_lists", + "enable_markdown_monospace_font", + "enable_defer", + "digest_after_minutes", + "automatically_unpin_topics", + "auto_track_topics_after_msecs", + "notification_level_when_replying", + "new_topic_duration_minutes", + "email_previous_replies", + "email_in_reply_to", + "like_notification_frequency", + "notify_on_linked_posts", + "include_tl0_in_digests", + "theme_ids", + "theme_key_seq", + "allow_private_messages", + "enable_allowed_pm_users", + "homepage_id", + "hide_profile_and_presence", + "hide_profile", + "hide_presence", + "text_size", + "text_size_seq", + "title_count_mode", + "timezone", + "skip_new_user_tips", + "topics_unread_when_closed", + "interface_color_mode", + "show_original_content" + ] + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "last_posted_at", + "last_seen_at", + "created_at", + "ignored", + "muted", + "can_ignore_user", + "can_mute_user", + "can_send_private_messages", + "can_send_private_message_to_user", + "trust_level", + "moderator", + "admin", + "title", + "badge_count", + "custom_fields", + "time_read", + "recent_time_read", + "primary_group_id", + "primary_group_name", + "flair_group_id", + "flair_name", + "flair_url", + "flair_bg_color", + "flair_color", + "featured_topic", + "staged", + "can_edit", + "can_edit_username", + "can_edit_email", + "can_edit_name", + "uploaded_avatar_id", + "has_title_badges", + "pending_count", + "profile_view_count", + "second_factor_enabled", + "can_upload_profile_header", + "can_upload_user_card_background", + "post_count", + "topic_count", + "can_be_deleted", + "can_delete_all_posts", + "locale", + "muted_category_ids", + "regular_category_ids", + "watched_tags", + "watching_first_post_tags", + "tracked_tags", + "muted_tags", + "tracked_category_ids", + "watched_category_ids", + "watched_first_post_category_ids", + "system_avatar_upload_id", + "system_avatar_template", + "muted_usernames", + "ignored_usernames", + "allowed_pm_usernames", + "mailing_list_posts_per_day", + "can_change_bio", + "can_change_location", + "can_change_website", + "can_change_tracking_preferences", + "user_api_keys", + "user_auth_tokens", + "user_notification_schedule", + "use_logo_small_as_avatar", + "featured_user_badge_ids", + "invited_by", + "groups", + "group_users", + "user_option" + ] + } + }, + "required": [ + "user_badges", + "user" + ] + } + } + } + } + } + } + }, + "/u/by-external/{provider}/{external_id}.json": { + "get": { + "summary": "Get a user by identity provider external ID", + "tags": [ + "Users" + ], + "operationId": "getUserIdentiyProviderExternalId", + "parameters": [ + { + "name": "Api-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Api-Username", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "provider", + "in": "path", + "required": true, + "description": "Authentication provider name. Can be found in the provider callback\nURL: `/auth/{provider}/callback`", + "schema": { + "type": "string" + } + }, + { + "name": "external_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "user response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "user_badges": { + "type": "array", + "items": {} + }, + "user": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "last_posted_at": { + "type": [ + "string", + "null" + ] + }, + "last_seen_at": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "ignored": { + "type": "boolean" + }, + "muted": { + "type": "boolean" + }, + "can_ignore_user": { + "type": "boolean" + }, + "can_ignore_users": { + "type": "boolean" + }, + "can_mute_user": { + "type": "boolean" + }, + "can_mute_users": { + "type": "boolean" + }, + "can_send_private_messages": { + "type": "boolean" + }, + "can_send_private_message_to_user": { + "type": "boolean" + }, + "trust_level": { + "type": "integer" + }, + "moderator": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "badge_count": { + "type": "integer" + }, + "second_factor_backup_enabled": { + "type": "boolean" + }, + "user_fields": { + "type": "object", + "additionalProperties": false, + "properties": { + "1": { + "type": [ + "string", + "null" + ] + }, + "2": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "1", + "2" + ] + }, + "custom_fields": { + "type": "object", + "additionalProperties": false, + "properties": { + "first_name": { + "type": [ + "string", + "null" + ] + } + } + }, + "time_read": { + "type": "integer" + }, + "recent_time_read": { + "type": "integer" + }, + "primary_group_id": { + "type": [ + "integer", + "null" + ] + }, + "primary_group_name": { + "type": [ + "string", + "null" + ] + }, + "flair_group_id": { + "type": [ + "integer", + "null" + ] + }, + "flair_name": { + "type": [ + "string", + "null" + ] + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "featured_topic": { + "type": [ + "string", + "null" + ] + }, + "staged": { + "type": "boolean" + }, + "can_edit": { + "type": "boolean" + }, + "can_edit_username": { + "type": "boolean" + }, + "can_edit_email": { + "type": "boolean" + }, + "can_edit_name": { + "type": "boolean" + }, + "uploaded_avatar_id": { + "type": [ + "integer", + "null" + ] + }, + "has_title_badges": { + "type": "boolean" + }, + "pending_count": { + "type": "integer" + }, + "pending_posts_count": { + "type": "integer" + }, + "profile_view_count": { + "type": "integer" + }, + "second_factor_enabled": { + "type": "boolean" + }, + "can_upload_profile_header": { + "type": "boolean" + }, + "can_upload_user_card_background": { + "type": "boolean" + }, + "post_count": { + "type": "integer" + }, + "topic_count": { + "type": "integer" + }, + "can_be_deleted": { + "type": "boolean" + }, + "can_delete_all_posts": { + "type": "boolean" + }, + "locale": { + "type": [ + "string", + "null" + ] + }, + "muted_category_ids": { + "type": "array", + "items": {} + }, + "regular_category_ids": { + "type": "array", + "items": {} + }, + "watched_tags": { + "type": "array", + "items": {} + }, + "watching_first_post_tags": { + "type": "array", + "items": {} + }, + "tracked_tags": { + "type": "array", + "items": {} + }, + "muted_tags": { + "type": "array", + "items": {} + }, + "tracked_category_ids": { + "type": "array", + "items": {} + }, + "watched_category_ids": { + "type": "array", + "items": {} + }, + "watched_first_post_category_ids": { + "type": "array", + "items": {} + }, + "system_avatar_upload_id": { + "type": [ + "string", + "null" + ] + }, + "system_avatar_template": { + "type": "string" + }, + "muted_usernames": { + "type": "array", + "items": {} + }, + "ignored_usernames": { + "type": "array", + "items": {} + }, + "allowed_pm_usernames": { + "type": "array", + "items": {} + }, + "mailing_list_posts_per_day": { + "type": "integer" + }, + "can_change_bio": { + "type": "boolean" + }, + "can_change_location": { + "type": "boolean" + }, + "can_change_website": { + "type": "boolean" + }, + "can_change_tracking_preferences": { + "type": "boolean" + }, + "user_api_keys": { + "type": [ + "string", + "null" + ] + }, + "user_passkeys": { + "type": "array" + }, + "sidebar_tags": { + "type": "array" + }, + "sidebar_category_ids": { + "type": "array" + }, + "display_sidebar_tags": { + "type": "boolean" + }, + "can_pick_theme_with_custom_homepage": { + "type": "boolean" + }, + "user_auth_tokens": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "client_ip": { + "type": "string" + }, + "location": { + "type": "string" + }, + "browser": { + "type": "string" + }, + "device": { + "type": "string" + }, + "os": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "seen_at": { + "type": "string" + }, + "is_active": { + "type": "boolean" + } + }, + "required": [ + "id", + "client_ip", + "location", + "browser", + "device", + "os", + "icon", + "created_at", + "seen_at", + "is_active" + ] + } + }, + "user_notification_schedule": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "day_0_start_time": { + "type": "integer" + }, + "day_0_end_time": { + "type": "integer" + }, + "day_1_start_time": { + "type": "integer" + }, + "day_1_end_time": { + "type": "integer" + }, + "day_2_start_time": { + "type": "integer" + }, + "day_2_end_time": { + "type": "integer" + }, + "day_3_start_time": { + "type": "integer" + }, + "day_3_end_time": { + "type": "integer" + }, + "day_4_start_time": { + "type": "integer" + }, + "day_4_end_time": { + "type": "integer" + }, + "day_5_start_time": { + "type": "integer" + }, + "day_5_end_time": { + "type": "integer" + }, + "day_6_start_time": { + "type": "integer" + }, + "day_6_end_time": { + "type": "integer" + } + }, + "required": [ + "enabled", + "day_0_start_time", + "day_0_end_time", + "day_1_start_time", + "day_1_end_time", + "day_2_start_time", + "day_2_end_time", + "day_3_start_time", + "day_3_end_time", + "day_4_start_time", + "day_4_end_time", + "day_5_start_time", + "day_5_end_time", + "day_6_start_time", + "day_6_end_time" + ] + }, + "use_logo_small_as_avatar": { + "type": "boolean" + }, + "featured_user_badge_ids": { + "type": "array", + "items": {} + }, + "invited_by": { + "type": [ + "string", + "null" + ] + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "automatic": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "user_count": { + "type": "integer" + }, + "mentionable_level": { + "type": "integer" + }, + "messageable_level": { + "type": "integer" + }, + "visibility_level": { + "type": "integer" + }, + "primary_group": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "grant_trust_level": { + "type": [ + "string", + "null" + ] + }, + "incoming_email": { + "type": [ + "string", + "null" + ] + }, + "has_messages": { + "type": "boolean" + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "bio_raw": { + "type": [ + "string", + "null" + ] + }, + "bio_cooked": { + "type": [ + "string", + "null" + ] + }, + "bio_excerpt": { + "type": [ + "string", + "null" + ] + }, + "public_admission": { + "type": "boolean" + }, + "public_exit": { + "type": "boolean" + }, + "allow_membership_requests": { + "type": "boolean" + }, + "full_name": { + "type": [ + "string", + "null" + ] + }, + "default_notification_level": { + "type": "integer" + }, + "membership_request_template": { + "type": [ + "string", + "null" + ] + }, + "members_visibility_level": { + "type": "integer" + }, + "can_see_members": { + "type": "boolean" + }, + "can_admin_group": { + "type": "boolean" + }, + "publish_read_state": { + "type": "boolean" + } + }, + "required": [ + "id", + "automatic", + "name", + "display_name", + "user_count", + "mentionable_level", + "messageable_level", + "visibility_level", + "primary_group", + "title", + "grant_trust_level", + "incoming_email", + "has_messages", + "flair_url", + "flair_bg_color", + "flair_color", + "bio_raw", + "bio_cooked", + "bio_excerpt", + "public_admission", + "public_exit", + "allow_membership_requests", + "full_name", + "default_notification_level", + "membership_request_template", + "members_visibility_level", + "can_see_members", + "can_admin_group", + "publish_read_state" + ] + } + }, + "group_users": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "group_id": { + "type": "integer" + }, + "user_id": { + "type": "integer" + }, + "notification_level": { + "type": "integer" + }, + "owner": { + "type": "boolean" + } + }, + "required": [ + "group_id", + "user_id", + "notification_level" + ] + } + }, + "user_option": { + "type": "object", + "additionalProperties": false, + "properties": { + "user_id": { + "type": "integer" + }, + "mailing_list_mode": { + "type": "boolean" + }, + "mailing_list_mode_frequency": { + "type": "integer" + }, + "email_digests": { + "type": "boolean" + }, + "email_level": { + "type": "integer" + }, + "email_messages_level": { + "type": "integer" + }, + "external_links_in_new_tab": { + "type": "boolean" + }, + "bookmark_auto_delete_preference": { + "type": "integer" + }, + "color_scheme_id": { + "type": [ + "string", + "null" + ] + }, + "dark_scheme_id": { + "type": [ + "string", + "null" + ] + }, + "dynamic_favicon": { + "type": "boolean" + }, + "enable_quoting": { + "type": "boolean" + }, + "enable_smart_lists": { + "type": "boolean" + }, + "enable_markdown_monospace_font": { + "type": "boolean" + }, + "enable_defer": { + "type": "boolean" + }, + "digest_after_minutes": { + "type": "integer" + }, + "automatically_unpin_topics": { + "type": "boolean" + }, + "auto_track_topics_after_msecs": { + "type": "integer" + }, + "notification_level_when_replying": { + "type": "integer" + }, + "new_topic_duration_minutes": { + "type": "integer" + }, + "email_previous_replies": { + "type": "integer" + }, + "email_in_reply_to": { + "type": "boolean" + }, + "like_notification_frequency": { + "type": "integer" + }, + "notify_on_linked_posts": { + "type": "boolean" + }, + "include_tl0_in_digests": { + "type": "boolean" + }, + "theme_ids": { + "type": "array", + "items": {} + }, + "theme_key_seq": { + "type": "integer" + }, + "allow_private_messages": { + "type": "boolean" + }, + "enable_allowed_pm_users": { + "type": "boolean" + }, + "homepage_id": { + "type": [ + "string", + "null" + ] + }, + "hide_profile_and_presence": { + "type": "boolean" + }, + "hide_profile": { + "type": "boolean" + }, + "hide_presence": { + "type": "boolean" + }, + "text_size": { + "type": "string" + }, + "text_size_seq": { + "type": "integer" + }, + "title_count_mode": { + "type": "string" + }, + "timezone": { + "type": [ + "string", + "null" + ] + }, + "skip_new_user_tips": { + "type": "boolean" + }, + "default_calendar": { + "type": "string" + }, + "oldest_search_log_date": { + "type": [ + "string", + "null" + ] + }, + "sidebar_link_to_filtered_list": { + "type": "boolean" + }, + "sidebar_show_count_of_new_items": { + "type": "boolean" + }, + "watched_precedence_over_muted": { + "type": [ + "boolean" + ] + }, + "seen_popups": { + "type": [ + "array", + "null" + ] + }, + "topics_unread_when_closed": { + "type": "boolean" + }, + "composition_mode": { + "type": "integer" + }, + "interface_color_mode": { + "type": "integer" + }, + "show_original_content": { + "type": "boolean" + } + }, + "required": [ + "user_id", + "mailing_list_mode", + "mailing_list_mode_frequency", + "email_digests", + "email_level", + "email_messages_level", + "external_links_in_new_tab", + "color_scheme_id", + "dark_scheme_id", + "dynamic_favicon", + "enable_quoting", + "enable_smart_lists", + "enable_markdown_monospace_font", + "enable_defer", + "digest_after_minutes", + "automatically_unpin_topics", + "auto_track_topics_after_msecs", + "notification_level_when_replying", + "new_topic_duration_minutes", + "email_previous_replies", + "email_in_reply_to", + "like_notification_frequency", + "notify_on_linked_posts", + "include_tl0_in_digests", + "theme_ids", + "theme_key_seq", + "allow_private_messages", + "enable_allowed_pm_users", + "homepage_id", + "hide_profile_and_presence", + "hide_profile", + "hide_presence", + "text_size", + "text_size_seq", + "title_count_mode", + "timezone", + "skip_new_user_tips", + "topics_unread_when_closed", + "interface_color_mode", + "show_original_content" + ] + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "last_posted_at", + "last_seen_at", + "created_at", + "ignored", + "muted", + "can_ignore_user", + "can_mute_user", + "can_send_private_messages", + "can_send_private_message_to_user", + "trust_level", + "moderator", + "admin", + "title", + "badge_count", + "custom_fields", + "time_read", + "recent_time_read", + "primary_group_id", + "primary_group_name", + "flair_group_id", + "flair_name", + "flair_url", + "flair_bg_color", + "flair_color", + "featured_topic", + "staged", + "can_edit", + "can_edit_username", + "can_edit_email", + "can_edit_name", + "uploaded_avatar_id", + "has_title_badges", + "pending_count", + "profile_view_count", + "second_factor_enabled", + "can_upload_profile_header", + "can_upload_user_card_background", + "post_count", + "topic_count", + "can_be_deleted", + "can_delete_all_posts", + "locale", + "muted_category_ids", + "regular_category_ids", + "watched_tags", + "watching_first_post_tags", + "tracked_tags", + "muted_tags", + "tracked_category_ids", + "watched_category_ids", + "watched_first_post_category_ids", + "system_avatar_upload_id", + "system_avatar_template", + "muted_usernames", + "ignored_usernames", + "allowed_pm_usernames", + "mailing_list_posts_per_day", + "can_change_bio", + "can_change_location", + "can_change_website", + "can_change_tracking_preferences", + "user_api_keys", + "user_auth_tokens", + "user_notification_schedule", + "use_logo_small_as_avatar", + "featured_user_badge_ids", + "invited_by", + "groups", + "group_users", + "user_option" + ] + } + }, + "required": [ + "user_badges", + "user" + ] + } + } + } + } + } + } + }, + "/u/{username}/preferences/avatar/pick.json": { + "put": { + "summary": "Update avatar", + "tags": [ + "Users" + ], + "operationId": "updateAvatar", + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "avatar updated", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string", + "example": "OK" + } + }, + "required": [ + "success" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "upload_id": { + "type": "integer" + }, + "type": { + "type": "string", + "enum": [ + "uploaded", + "custom", + "gravatar", + "system" + ] + } + }, + "required": [ + "upload_id", + "type" + ] + } + } + } + } + } + }, + "/u/{username}/preferences/email.json": { + "put": { + "summary": "Update email", + "tags": [ + "Users" + ], + "operationId": "updateEmail", + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "email updated" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "email": { + "type": "string", + "format": "email" + } + }, + "required": [ + "email" + ] + } + } + } + } + } + }, + "/u/{username}/preferences/username.json": { + "put": { + "summary": "Update username", + "tags": [ + "Users" + ], + "operationId": "updateUsername", + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "username updated" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "new_username": { + "type": "string" + } + }, + "required": [ + "new_username" + ] + } + } + } + } + } + }, + "/directory_items.json": { + "get": { + "summary": "Get a public list of users", + "tags": [ + "Users" + ], + "operationId": "listUsersPublic", + "parameters": [ + { + "name": "period", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "daily", + "weekly", + "monthly", + "quarterly", + "yearly", + "all" + ] + }, + "required": true + }, + { + "name": "order", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "likes_received", + "likes_given", + "topic_count", + "post_count", + "topics_entered", + "posts_read", + "days_visited" + ] + }, + "required": true + }, + { + "name": "asc", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "true" + ] + } + }, + { + "name": "page", + "in": "query", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "directory items response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "directory_items": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "likes_received": { + "type": "integer" + }, + "likes_given": { + "type": "integer" + }, + "topics_entered": { + "type": "integer" + }, + "topic_count": { + "type": "integer" + }, + "post_count": { + "type": "integer" + }, + "posts_read": { + "type": "integer" + }, + "days_visited": { + "type": "integer" + }, + "user": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + }, + "title": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "title" + ] + } + }, + "required": [ + "id", + "likes_received", + "likes_given", + "topics_entered", + "topic_count", + "post_count", + "posts_read", + "days_visited", + "user" + ] + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "last_updated_at": { + "type": [ + "string", + "null" + ] + }, + "total_rows_directory_items": { + "type": "integer" + }, + "load_more_directory_items": { + "type": "string" + } + }, + "required": [ + "last_updated_at", + "total_rows_directory_items", + "load_more_directory_items" + ] + } + }, + "required": [ + "directory_items", + "meta" + ] + } + } + } + } + } + } + }, + "/admin/users/{id}.json": { + "get": { + "summary": "Get a user by id", + "tags": [ + "Users", + "Admin" + ], + "operationId": "adminGetUser", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + }, + "active": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "moderator": { + "type": "boolean" + }, + "last_seen_at": { + "type": [ + "string", + "null" + ] + }, + "last_emailed_at": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "last_seen_age": { + "type": [ + "number", + "null" + ] + }, + "last_emailed_age": { + "type": [ + "number", + "null" + ] + }, + "created_at_age": { + "type": [ + "number", + "null" + ] + }, + "trust_level": { + "type": "integer" + }, + "manual_locked_trust_level": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "time_read": { + "type": "integer" + }, + "staged": { + "type": "boolean" + }, + "days_visited": { + "type": "integer" + }, + "posts_read_count": { + "type": "integer" + }, + "topics_entered": { + "type": "integer" + }, + "post_count": { + "type": "integer" + }, + "associated_accounts": { + "type": "array", + "items": {} + }, + "can_send_activation_email": { + "type": "boolean" + }, + "can_activate": { + "type": "boolean" + }, + "can_deactivate": { + "type": "boolean" + }, + "can_change_trust_level": { + "type": "boolean" + }, + "ip_address": { + "type": "string" + }, + "registration_ip_address": { + "type": [ + "string", + "null" + ] + }, + "can_grant_admin": { + "type": "boolean" + }, + "can_revoke_admin": { + "type": "boolean" + }, + "can_grant_moderation": { + "type": "boolean" + }, + "can_revoke_moderation": { + "type": "boolean" + }, + "can_impersonate": { + "type": "boolean" + }, + "like_count": { + "type": "integer" + }, + "like_given_count": { + "type": "integer" + }, + "topic_count": { + "type": "integer" + }, + "flags_given_count": { + "type": "integer" + }, + "flags_received_count": { + "type": "integer" + }, + "private_topics_count": { + "type": "integer" + }, + "can_delete_all_posts": { + "type": "boolean" + }, + "can_be_deleted": { + "type": "boolean" + }, + "can_be_anonymized": { + "type": "boolean" + }, + "can_be_merged": { + "type": "boolean" + }, + "full_suspend_reason": { + "type": [ + "string", + "null" + ] + }, + "latest_export": { + "type": [ + "object", + "null" + ] + }, + "full_silence_reason": { + "type": [ + "string", + "null" + ] + }, + "silence_reason": { + "type": [ + "string", + "null" + ] + }, + "post_edits_count": { + "type": [ + "integer", + "null" + ] + }, + "primary_group_id": { + "type": [ + "integer", + "null" + ] + }, + "badge_count": { + "type": "integer" + }, + "warnings_received_count": { + "type": "integer" + }, + "bounce_score": { + "type": [ + "integer", + "null" + ] + }, + "reset_bounce_score_after": { + "type": [ + "string", + "null" + ] + }, + "can_view_action_logs": { + "type": "boolean" + }, + "can_disable_second_factor": { + "type": "boolean" + }, + "can_delete_sso_record": { + "type": "boolean" + }, + "api_key_count": { + "type": "integer" + }, + "similar_users_count": { + "type": "integer" + }, + "single_sign_on_record": { + "type": [ + "string", + "null" + ] + }, + "approved_by": { + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template" + ] + }, + "suspended_by": { + "type": [ + "string", + "null" + ] + }, + "silenced_by": { + "type": [ + "string", + "null" + ] + }, + "penalty_counts": { + "type": "object", + "additionalProperties": false, + "properties": { + "silenced": { + "type": "integer" + }, + "suspended": { + "type": "integer" + } + }, + "required": [ + "silenced", + "suspended" + ] + }, + "next_penalty": { + "type": "string" + }, + "tl3_requirements": { + "type": "object", + "additionalProperties": false, + "properties": { + "time_period": { + "type": "integer" + }, + "requirements_met": { + "type": "boolean" + }, + "requirements_lost": { + "type": "boolean" + }, + "trust_level_locked": { + "type": "boolean" + }, + "on_grace_period": { + "type": "boolean" + }, + "days_visited": { + "type": "integer" + }, + "min_days_visited": { + "type": "integer" + }, + "num_topics_replied_to": { + "type": "integer" + }, + "min_topics_replied_to": { + "type": "integer" + }, + "topics_viewed": { + "type": "integer" + }, + "min_topics_viewed": { + "type": "integer" + }, + "posts_read": { + "type": "integer" + }, + "min_posts_read": { + "type": "integer" + }, + "topics_viewed_all_time": { + "type": "integer" + }, + "min_topics_viewed_all_time": { + "type": "integer" + }, + "posts_read_all_time": { + "type": "integer" + }, + "min_posts_read_all_time": { + "type": "integer" + }, + "num_flagged_posts": { + "type": "integer" + }, + "max_flagged_posts": { + "type": "integer" + }, + "num_flagged_by_users": { + "type": "integer" + }, + "max_flagged_by_users": { + "type": "integer" + }, + "num_likes_given": { + "type": "integer" + }, + "min_likes_given": { + "type": "integer" + }, + "num_likes_received": { + "type": "integer" + }, + "min_likes_received": { + "type": "integer" + }, + "num_likes_received_days": { + "type": "integer" + }, + "min_likes_received_days": { + "type": "integer" + }, + "num_likes_received_users": { + "type": "integer" + }, + "min_likes_received_users": { + "type": "integer" + }, + "penalty_counts": { + "type": "object", + "additionalProperties": false, + "properties": { + "silenced": { + "type": "integer" + }, + "suspended": { + "type": "integer" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "silenced", + "suspended", + "total" + ] + } + }, + "required": [ + "time_period", + "requirements_met", + "requirements_lost", + "trust_level_locked", + "on_grace_period", + "days_visited", + "min_days_visited", + "num_topics_replied_to", + "min_topics_replied_to", + "topics_viewed", + "min_topics_viewed", + "posts_read", + "min_posts_read", + "topics_viewed_all_time", + "min_topics_viewed_all_time", + "posts_read_all_time", + "min_posts_read_all_time", + "num_flagged_posts", + "max_flagged_posts", + "num_flagged_by_users", + "max_flagged_by_users", + "num_likes_given", + "min_likes_given", + "num_likes_received", + "min_likes_received", + "num_likes_received_days", + "min_likes_received_days", + "num_likes_received_users", + "min_likes_received_users", + "penalty_counts" + ] + }, + "groups": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "automatic": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "user_count": { + "type": "integer" + }, + "mentionable_level": { + "type": "integer" + }, + "messageable_level": { + "type": "integer" + }, + "visibility_level": { + "type": "integer" + }, + "primary_group": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "grant_trust_level": { + "type": [ + "string", + "null" + ] + }, + "incoming_email": { + "type": [ + "string", + "null" + ] + }, + "has_messages": { + "type": "boolean" + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "flair_group_id": { + "type": [ + "integer", + "null" + ] + }, + "bio_raw": { + "type": [ + "string", + "null" + ] + }, + "bio_cooked": { + "type": [ + "string", + "null" + ] + }, + "bio_excerpt": { + "type": [ + "string", + "null" + ] + }, + "public_admission": { + "type": "boolean" + }, + "public_exit": { + "type": "boolean" + }, + "allow_membership_requests": { + "type": "boolean" + }, + "full_name": { + "type": [ + "string", + "null" + ] + }, + "default_notification_level": { + "type": "integer" + }, + "membership_request_template": { + "type": [ + "string", + "null" + ] + }, + "members_visibility_level": { + "type": "integer" + }, + "can_see_members": { + "type": "boolean" + }, + "can_admin_group": { + "type": "boolean" + }, + "publish_read_state": { + "type": "boolean" + } + }, + "required": [ + "id", + "automatic", + "name", + "display_name", + "user_count", + "mentionable_level", + "messageable_level", + "visibility_level", + "primary_group", + "title", + "grant_trust_level", + "incoming_email", + "has_messages", + "flair_url", + "flair_bg_color", + "flair_color", + "bio_raw", + "bio_cooked", + "bio_excerpt", + "public_admission", + "public_exit", + "allow_membership_requests", + "full_name", + "default_notification_level", + "membership_request_template", + "members_visibility_level", + "can_see_members", + "can_admin_group", + "publish_read_state" + ] + } + }, + "external_ids": { + "type": "object" + }, + "include_ip": { + "type": "boolean" + }, + "upcoming_changes_stats": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "humanized_name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "specific_groups": { + "type": "array", + "items": { + "type": "string" + } + }, + "reason": { + "type": "string", + "enum": [ + "enabled_for_everyone", + "enabled_for_no_one", + "in_specific_groups", + "not_in_specific_groups" + ] + } + }, + "required": [ + "name", + "humanized_name", + "description", + "enabled", + "specific_groups", + "reason" + ] + } + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "active", + "admin", + "moderator", + "last_seen_at", + "last_emailed_at", + "created_at", + "last_seen_age", + "last_emailed_age", + "created_at_age", + "trust_level", + "manual_locked_trust_level", + "title", + "time_read", + "staged", + "days_visited", + "posts_read_count", + "topics_entered", + "post_count", + "can_send_activation_email", + "can_activate", + "can_deactivate", + "ip_address", + "registration_ip_address", + "can_grant_admin", + "can_revoke_admin", + "can_grant_moderation", + "can_revoke_moderation", + "can_impersonate", + "like_count", + "like_given_count", + "topic_count", + "flags_given_count", + "flags_received_count", + "private_topics_count", + "can_delete_all_posts", + "can_be_anonymized", + "can_be_merged", + "full_suspend_reason", + "primary_group_id", + "badge_count", + "warnings_received_count", + "bounce_score", + "reset_bounce_score_after", + "can_view_action_logs", + "can_disable_second_factor", + "can_delete_sso_record", + "api_key_count", + "single_sign_on_record", + "approved_by", + "suspended_by", + "silenced_by", + "groups", + "external_ids", + "include_ip" + ] + } + } + } + } + } + }, + "delete": { + "summary": "Delete a user", + "tags": [ + "Users", + "Admin" + ], + "operationId": "deleteUser", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "deleted": { + "type": "boolean" + } + }, + "required": [ + "deleted" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "delete_posts": { + "type": "boolean" + }, + "block_email": { + "type": "boolean" + }, + "block_urls": { + "type": "boolean" + }, + "block_ip": { + "type": "boolean" + } + } + } + } + } + } + } + }, + "/admin/users/{id}/activate.json": { + "put": { + "summary": "Activate a user", + "tags": [ + "Users", + "Admin" + ], + "operationId": "activateUser", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string", + "example": "OK" + } + }, + "required": [ + "success" + ] + } + } + } + } + } + } + }, + "/admin/users/{id}/deactivate.json": { + "put": { + "summary": "Deactivate a user", + "tags": [ + "Users", + "Admin" + ], + "operationId": "deactivateUser", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string", + "example": "OK" + } + }, + "required": [ + "success" + ] + } + } + } + } + } + } + }, + "/admin/users/{id}/suspend.json": { + "put": { + "summary": "Suspend a user", + "tags": [ + "Users", + "Admin" + ], + "operationId": "suspendUser", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "suspension": { + "type": "object", + "additionalProperties": false, + "properties": { + "suspend_reason": { + "type": "string" + }, + "full_suspend_reason": { + "type": "string" + }, + "suspended_till": { + "type": "string" + }, + "suspended_at": { + "type": "string" + }, + "suspended_by": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template" + ] + } + }, + "required": [ + "suspend_reason", + "full_suspend_reason", + "suspended_till", + "suspended_at", + "suspended_by" + ] + } + }, + "required": [ + "suspension" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "suspend_until": { + "type": "string", + "example": "2121-02-22" + }, + "reason": { + "type": "string" + }, + "message": { + "type": "string", + "description": "Will send an email with this message when present" + }, + "post_action": { + "type": "string", + "example": "delete" + } + }, + "required": [ + "suspend_until", + "reason" + ] + } + } + } + } + } + }, + "/admin/users/{id}/silence.json": { + "put": { + "summary": "Silence a user", + "tags": [ + "Users", + "Admin" + ], + "operationId": "silenceUser", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "silence": { + "type": "object", + "additionalProperties": false, + "properties": { + "silenced": { + "type": "boolean" + }, + "silence_reason": { + "type": "string" + }, + "full_silence_reason": { + "type": "string" + }, + "silenced_till": { + "type": "string" + }, + "silenced_at": { + "type": "string" + }, + "silenced_by": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template" + ] + } + }, + "required": [ + "silenced", + "silence_reason", + "full_silence_reason", + "silenced_till", + "silenced_at", + "silenced_by" + ] + } + }, + "required": [ + "silence" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "silenced_till": { + "type": "string", + "example": "2022-06-01T08:00:00.000Z" + }, + "reason": { + "type": "string" + }, + "message": { + "type": "string", + "description": "Will send an email with this message when present" + }, + "post_action": { + "type": "string", + "example": "delete" + } + }, + "required": [ + "silenced_till", + "reason" + ] + } + } + } + } + } + }, + "/admin/users/{id}/anonymize.json": { + "put": { + "summary": "Anonymize a user", + "tags": [ + "Users", + "Admin" + ], + "operationId": "anonymizeUser", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "success", + "username" + ] + } + } + } + } + } + } + }, + "/admin/users/{id}/log_out.json": { + "post": { + "summary": "Log a user out", + "tags": [ + "Users", + "Admin" + ], + "operationId": "logOutUser", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string", + "example": "OK" + } + }, + "required": [ + "success" + ] + } + } + } + } + } + } + }, + "/user_avatar/{username}/refresh_gravatar.json": { + "post": { + "summary": "Refresh gravatar", + "tags": [ + "Users", + "Admin" + ], + "operationId": "refreshGravatar", + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "gravatar_upload_id": { + "type": [ + "integer", + "null" + ] + }, + "gravatar_avatar_template": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "gravatar_upload_id", + "gravatar_avatar_template" + ] + } + } + } + } + } + } + }, + "/admin/users.json": { + "get": { + "summary": "List users", + "tags": [ + "Users", + "Admin" + ], + "operationId": "adminListUsers", + "parameters": [ + { + "name": "order", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "created", + "last_emailed", + "seen", + "username", + "email", + "trust_level", + "days_visited", + "posts_read", + "topics_viewed", + "posts", + "read_time" + ] + } + }, + { + "name": "asc", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "true" + ] + } + }, + { + "name": "page", + "in": "query", + "schema": { + "type": "integer" + } + }, + { + "name": "show_emails", + "in": "query", + "description": "Include user email addresses in response. These requests will\nbe logged in the staff action logs.", + "schema": { + "type": "boolean" + } + }, + { + "name": "stats", + "in": "query", + "description": "Include user stats information", + "schema": { + "type": "boolean" + } + }, + { + "name": "email", + "in": "query", + "description": "Filter to the user with this email address", + "schema": { + "type": "string" + } + }, + { + "name": "ip", + "in": "query", + "description": "Filter to users with this IP address", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "users response", + "content": { + "application/json": { + "schema": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + }, + "email": { + "type": "string" + }, + "secondary_emails": { + "type": "array", + "items": {} + }, + "active": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "moderator": { + "type": "boolean" + }, + "last_seen_at": { + "type": [ + "string", + "null" + ] + }, + "last_emailed_at": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "last_seen_age": { + "type": [ + "number", + "null" + ] + }, + "last_emailed_age": { + "type": [ + "number", + "null" + ] + }, + "created_at_age": { + "type": [ + "number", + "null" + ] + }, + "trust_level": { + "type": "integer" + }, + "manual_locked_trust_level": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "time_read": { + "type": "integer" + }, + "staged": { + "type": "boolean" + }, + "days_visited": { + "type": "integer" + }, + "posts_read_count": { + "type": "integer" + }, + "topics_entered": { + "type": "integer" + }, + "post_count": { + "type": "integer" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "active", + "admin", + "moderator", + "last_seen_at", + "last_emailed_at", + "created_at", + "last_seen_age", + "last_emailed_age", + "created_at_age", + "trust_level", + "manual_locked_trust_level", + "title", + "time_read", + "staged", + "days_visited", + "posts_read_count", + "topics_entered", + "post_count" + ] + } + } + } + } + } + } + } + }, + "/admin/users/list/{flag}.json": { + "get": { + "summary": "List users by flag", + "tags": [ + "Users", + "Admin" + ], + "operationId": "adminListUsersFlag", + "parameters": [ + { + "name": "flag", + "in": "path", + "schema": { + "type": "string", + "enum": [ + "active", + "new", + "staff", + "suspended", + "blocked", + "suspect" + ] + }, + "required": true + }, + { + "name": "order", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "created", + "last_emailed", + "seen", + "username", + "email", + "trust_level", + "days_visited", + "posts_read", + "topics_viewed", + "posts", + "read_time" + ] + } + }, + { + "name": "asc", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "true" + ] + } + }, + { + "name": "page", + "in": "query", + "schema": { + "type": "integer" + } + }, + { + "name": "show_emails", + "in": "query", + "description": "Include user email addresses in response. These requests will\nbe logged in the staff action logs.", + "schema": { + "type": "boolean" + } + }, + { + "name": "stats", + "in": "query", + "description": "Include user stats information", + "schema": { + "type": "boolean" + } + }, + { + "name": "email", + "in": "query", + "description": "Filter to the user with this email address", + "schema": { + "type": "string" + } + }, + { + "name": "ip", + "in": "query", + "description": "Filter to users with this IP address", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + }, + "email": { + "type": "string" + }, + "secondary_emails": { + "type": "array", + "items": {} + }, + "active": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "moderator": { + "type": "boolean" + }, + "last_seen_at": { + "type": [ + "string", + "null" + ] + }, + "last_emailed_at": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "last_seen_age": { + "type": [ + "number", + "null" + ] + }, + "last_emailed_age": { + "type": [ + "number", + "null" + ] + }, + "created_at_age": { + "type": [ + "number", + "null" + ] + }, + "trust_level": { + "type": "integer" + }, + "manual_locked_trust_level": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "time_read": { + "type": "integer" + }, + "staged": { + "type": "boolean" + }, + "days_visited": { + "type": "integer" + }, + "posts_read_count": { + "type": "integer" + }, + "topics_entered": { + "type": "integer" + }, + "post_count": { + "type": "integer" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "active", + "admin", + "moderator", + "last_seen_at", + "last_emailed_at", + "created_at", + "last_seen_age", + "last_emailed_age", + "created_at_age", + "trust_level", + "manual_locked_trust_level", + "title", + "time_read", + "staged", + "days_visited", + "posts_read_count", + "topics_entered", + "post_count" + ] + } + } + } + } + } + } + } + }, + "/user_actions.json": { + "get": { + "summary": "Get a list of user actions", + "tags": [ + "Users" + ], + "operationId": "listUserActions", + "parameters": [ + { + "name": "offset", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "username", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "filter", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "user_actions": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "excerpt": { + "type": "string" + }, + "action_type": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "acting_avatar_template": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "topic_id": { + "type": "integer" + }, + "target_user_id": { + "type": "integer" + }, + "target_name": { + "type": [ + "string", + "null" + ] + }, + "target_username": { + "type": "string" + }, + "post_number": { + "type": "integer" + }, + "post_id": { + "type": [ + "string", + "null" + ] + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "user_id": { + "type": "integer" + }, + "acting_username": { + "type": "string" + }, + "acting_name": { + "type": [ + "string", + "null" + ] + }, + "acting_user_id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "deleted": { + "type": "boolean" + }, + "hidden": { + "type": [ + "string", + "null" + ] + }, + "post_type": { + "type": [ + "string", + "null" + ] + }, + "action_code": { + "type": [ + "string", + "null" + ] + }, + "category_id": { + "type": "integer" + }, + "closed": { + "type": "boolean" + }, + "archived": { + "type": "boolean" + } + }, + "required": [ + "excerpt", + "action_type", + "created_at", + "avatar_template", + "acting_avatar_template", + "slug", + "topic_id", + "target_user_id", + "target_name", + "target_username", + "post_number", + "post_id", + "username", + "name", + "user_id", + "acting_username", + "acting_name", + "acting_user_id", + "title", + "deleted", + "hidden", + "post_type", + "action_code", + "category_id", + "closed", + "archived" + ] + } + } + }, + "required": [ + "user_actions" + ] + } + } + } + } + } + } + }, + "/session/forgot_password.json": { + "post": { + "summary": "Send password reset email", + "tags": [ + "Users" + ], + "operationId": "sendPasswordResetEmail", + "parameters": [], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "success": { + "type": "string" + }, + "user_found": { + "type": "boolean" + } + }, + "required": [ + "success", + "user_found" + ] + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "login": { + "type": "string" + } + }, + "required": [ + "login" + ] + } + } + } + } + } + }, + "/users/password-reset/{token}.json": { + "put": { + "summary": "Change password", + "tags": [ + "Users" + ], + "operationId": "changePassword", + "parameters": [ + { + "name": "token", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "success response" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "username": { + "type": "string" + }, + "password": { + "type": "string" + } + }, + "required": [ + "username", + "password" + ] + } + } + } + } + } + }, + "/u/{username}/emails.json": { + "get": { + "summary": "Get email addresses belonging to a user", + "tags": [ + "Users" + ], + "operationId": "getUserEmails", + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "success response", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "email": { + "type": "string" + }, + "secondary_emails": { + "type": "array", + "items": {} + }, + "unconfirmed_emails": { + "type": "array", + "items": {} + }, + "associated_accounts": { + "type": "array", + "items": {} + } + }, + "required": [ + "email", + "secondary_emails", + "unconfirmed_emails", + "associated_accounts" + ] + } + } + } + } + } + } + } + }, + "components": { + "schemas": {} + } +} \ No newline at end of file diff --git a/fuzz/seeds/notion.json b/fuzz/seeds/notion.json new file mode 100644 index 0000000..957104f --- /dev/null +++ b/fuzz/seeds/notion.json @@ -0,0 +1 @@ +{"openapi": "3.1.0", "info": {"title": "Notion API", "version": "2.0.0", "description": "Notion API 2025-09-03 - Data Source Edition. Breaking change: Database endpoints replaced with data source endpoints.", "license": {"name": "MIT", "url": "https://github.com/makenotion/notion-sdk-js/blob/main/LICENSE"}}, "components": {"securitySchemes": {"bearerAuth": {"type": "http", "scheme": "bearer"}, "basicAuth": {"type": "http", "scheme": "basic"}}, "parameters": {"notionVersion": {"name": "Notion-Version", "in": "header", "required": false, "schema": {"type": "string", "default": "2025-09-03"}, "description": "The Notion API version"}}, "schemas": {"richTextRequest": {"type": "object", "required": ["text"], "properties": {"text": {"type": "object", "required": ["content"], "properties": {"content": {"type": "string"}, "link": {"type": ["object", "null"], "properties": {"url": {"type": "string"}}, "required": ["url"]}}, "additionalProperties": false}, "type": {"enum": ["text"], "type": "string"}}, "additionalProperties": false}, "pageIdParentRequest": {"type": "object", "properties": {"page_id": {"type": "string", "format": "uuid"}}, "required": ["page_id"]}, "dataSourceIdParentRequest": {"type": "object", "properties": {"type": {"type": "string", "const": "database_id"}, "database_id": {"type": "string", "format": "uuid"}}, "required": ["database_id"]}, "parentRequest": {"oneOf": [{"$ref": "#/components/schemas/pageIdParentRequest"}, {"$ref": "#/components/schemas/dataSourceIdParentRequest"}, {"type": "object", "properties": {"type": {"const": "workspace"}}, "required": ["type"]}]}, "movePageParentRequest": {"oneOf": [{"type": "object", "properties": {"type": {"const": "page_id"}, "page_id": {"type": "string", "format": "uuid"}}, "required": ["type", "page_id"]}, {"type": "object", "properties": {"type": {"const": "database_id"}, "database_id": {"type": "string", "format": "uuid"}}, "required": ["type", "database_id"]}, {"type": "object", "properties": {"type": {"const": "workspace"}}, "required": ["type"]}]}, "sortObject": {"type": "object", "required": ["property", "direction"], "properties": {"property": {"type": "string"}, "direction": {"enum": ["ascending", "descending"], "type": "string"}}}, "paragraphBlockRequest": {"type": "object", "properties": {"paragraph": {"type": "object", "properties": {"rich_text": {"type": "array", "items": {"$ref": "#/components/schemas/richTextRequest"}, "maxItems": 100}}, "additionalProperties": false, "required": ["rich_text"]}, "type": {"enum": ["paragraph"], "type": "string"}}, "additionalProperties": false}, "bulletedListItemBlockRequest": {"type": "object", "properties": {"bulleted_list_item": {"type": "object", "properties": {"rich_text": {"type": "array", "items": {"$ref": "#/components/schemas/richTextRequest"}, "maxItems": 100}}, "additionalProperties": false, "required": ["rich_text"]}, "type": {"enum": ["bulleted_list_item"], "type": "string"}}, "additionalProperties": false}, "blockObjectRequest": {"anyOf": [{"$ref": "#/components/schemas/paragraphBlockRequest"}, {"$ref": "#/components/schemas/bulletedListItemBlockRequest"}]}}}, "security": [{"bearerAuth": []}], "tags": [{"name": "Databases", "description": "Database endpoints for retrieving database metadata"}, {"name": "Data sources", "description": "Data source endpoints for querying and managing databases"}, {"name": "Pages", "description": "Page endpoints for creating and managing pages"}, {"name": "Blocks", "description": "Block endpoints for managing page content"}, {"name": "Users", "description": "User endpoints"}, {"name": "Search", "description": "Search endpoints"}, {"name": "Comments", "description": "Comment endpoints"}], "paths": {"/v1/users/{user_id}": {"get": {"summary": "Retrieve a user", "description": "", "operationId": "get-user", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"$ref": "#/components/parameters/notionVersion"}], "responses": {"200": {"description": "200", "content": {"application/json": {"examples": {}}}}, "400": {"description": "400", "content": {"application/json": {"examples": {"Result": {"value": {}}}, "schema": {"type": "object", "properties": {}}}}}}, "deprecated": false, "security": []}}, "/v1/users": {"get": {"summary": "List all users", "operationId": "get-users", "parameters": [{"name": "start_cursor", "in": "query", "description": "If supplied, this endpoint will return a page of results starting after the cursor provided. If not supplied, this endpoint will return the first page of results.", "schema": {"type": "string"}}, {"name": "page_size", "in": "query", "description": "The number of items from the full list desired in the response. Maximum: 100", "schema": {"type": "integer", "default": 100}}, {"$ref": "#/components/parameters/notionVersion"}], "responses": {"400": {"description": "400", "content": {"application/json": {"examples": {"Result": {"value": {}}}, "schema": {"type": "object", "properties": {}}}}}, "200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}}, "deprecated": false}}, "/v1/users/me": {"get": {"summary": "Retrieve your token's bot user", "description": "", "operationId": "get-self", "parameters": [{"$ref": "#/components/parameters/notionVersion"}], "responses": {"200": {"description": "200", "content": {"application/json": {"examples": {"Result": {"value": {"object": "user", "id": "16d84278-ab0e-484c-9bdd-b35da3bd8905", "name": "pied piper", "avatar_url": null, "type": "bot", "bot": {"owner": {"type": "user", "user": {"object": "user", "id": "5389a034-eb5c-47b5-8a9e-f79c99ef166c", "name": "christine makenotion", "avatar_url": null, "type": "person", "person": {"email": "christine@makenotion.com"}}}}}}}, "schema": {"type": "object", "properties": {"object": {"type": "string", "example": "user"}, "id": {"type": "string", "example": "16d84278-ab0e-484c-9bdd-b35da3bd8905"}, "name": {"type": "string", "example": "pied piper"}, "avatar_url": {}, "type": {"type": "string", "example": "bot"}, "bot": {"type": "object", "properties": {"owner": {"type": "object", "properties": {"type": {"type": "string", "example": "user"}, "user": {"type": "object", "properties": {"object": {"type": "string", "example": "user"}, "id": {"type": "string", "example": "5389a034-eb5c-47b5-8a9e-f79c99ef166c"}, "name": {"type": "string", "example": "christine makenotion"}, "avatar_url": {}, "type": {"type": "string", "example": "person"}, "person": {"type": "object", "properties": {"email": {"type": "string", "example": "christine@makenotion.com"}}}}}}}}}}}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/search": {"post": {"summary": "Search by title", "description": "", "operationId": "post-search", "parameters": [{"$ref": "#/components/parameters/notionVersion"}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"query": {"type": "string", "description": "The text that the API compares page and database titles against."}, "sort": {"type": "object", "description": "A set of criteria, `direction` and `timestamp` keys, that orders the results. The **only** supported timestamp value is `\"last_edited_time\"`. Supported `direction` values are `\"ascending\"` and `\"descending\"`. If `sort` is not provided, then the most recently edited results are returned first.", "properties": {"direction": {"type": "string", "description": "The direction to sort. Possible values include `ascending` and `descending`."}, "timestamp": {"type": "string", "description": "The name of the timestamp to sort against. Possible values include `last_edited_time`."}}}, "filter": {"type": "object", "description": "A set of criteria, `value` and `property` keys, that limits the results to either only pages or only data sources. Possible `value` values are `\"page\"` or `\"data_source\"`. The only supported `property` value is `\"object\"`.", "properties": {"value": {"type": "string", "description": "The value of the property to filter the results by. Possible values for object type include `page` or `data_source`. **Limitation**: Currently the only filter allowed is `object` which will filter by type of object (either `page` or `data_source`)", "enum": ["page", "data_source"]}, "property": {"type": "string", "description": "The name of the property to filter by. Currently the only property you can filter by is the object type. Possible values include `object`. Limitation: Currently the only filter allowed is `object` which will filter by type of object (either `page` or `data_source`)"}}}, "start_cursor": {"type": "string", "description": "A `cursor` value returned in a previous response that If supplied, limits the response to results starting after the `cursor`. If not supplied, then the first page of results is returned. Refer to [pagination](https://developers.notion.com/reference/intro#pagination) for more details."}, "page_size": {"type": "integer", "description": "The number of items from the full list to include in the response. Maximum: `100`.", "default": 100, "format": "int32"}}}}}}, "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/blocks/{block_id}/children": {"get": {"summary": "Retrieve block children", "description": "", "operationId": "get-block-children", "parameters": [{"name": "block_id", "in": "path", "description": "Identifier for a [block](ref:block)", "schema": {"type": "string"}, "required": true}, {"name": "start_cursor", "in": "query", "description": "If supplied, this endpoint will return a page of results starting after the cursor provided. If not supplied, this endpoint will return the first page of results.", "schema": {"type": "string"}}, {"name": "page_size", "in": "query", "description": "The number of items from the full list desired in the response. Maximum: 100", "schema": {"type": "integer", "format": "int32", "default": 100}}, {"$ref": "#/components/parameters/notionVersion"}], "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}, "patch": {"summary": "Append block children", "description": "", "operationId": "patch-block-children", "parameters": [{"name": "block_id", "in": "path", "description": "Identifier for a [block](ref:block). Also accepts a [page](ref:page) ID.", "schema": {"type": "string"}, "required": true}, {"$ref": "#/components/parameters/notionVersion"}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "required": ["children"], "properties": {"children": {"type": "array", "items": {"$ref": "#/components/schemas/blockObjectRequest"}, "description": "Child content to append to a container block as an array of [block objects](ref:block)"}, "after": {"type": "string", "description": "The ID of the existing block that the new block should be appended after."}}}}}}, "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/blocks/{block_id}": {"get": {"summary": "Retrieve a block", "description": "", "operationId": "retrieve-a-block", "parameters": [{"name": "block_id", "in": "path", "description": "Identifier for a Notion block", "schema": {"type": "string"}, "required": true}, {"$ref": "#/components/parameters/notionVersion"}], "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}, "patch": {"summary": "Update a block", "description": "", "operationId": "update-a-block", "parameters": [{"name": "block_id", "in": "path", "description": "Identifier for a Notion block", "schema": {"type": "string"}, "required": true}, {"$ref": "#/components/parameters/notionVersion"}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"type": {"type": "object", "description": "The [block object `type`](ref:block#block-object-keys) value with the properties to be updated. Currently only `text` (for supported block types) and `checked` (for `to_do` blocks) fields can be updated.", "properties": {}}, "archived": {"type": "boolean", "description": "Set to true to archive (delete) a block. Set to false to un-archive (restore) a block.", "default": true}}}}}}, "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}, "delete": {"summary": "Delete a block", "description": "", "operationId": "delete-a-block", "parameters": [{"name": "block_id", "in": "path", "description": "Identifier for a Notion block", "schema": {"type": "string"}, "required": true}, {"$ref": "#/components/parameters/notionVersion"}], "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/pages/{page_id}": {"get": {"summary": "Retrieve a page", "description": "", "operationId": "retrieve-a-page", "parameters": [{"name": "page_id", "in": "path", "description": "Identifier for a Notion page", "schema": {"type": "string"}, "required": true}, {"name": "filter_properties", "in": "query", "description": "A list of page property value IDs associated with the page. Use this param to limit the response to a specific page property value or values. To retrieve multiple properties, specify each page property ID. For example: `?filter_properties=iAk8&filter_properties=b7dh`.", "schema": {"type": "string"}}, {"$ref": "#/components/parameters/notionVersion"}], "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}, "patch": {"summary": "Update page properties", "description": "", "operationId": "patch-page", "parameters": [{"name": "page_id", "in": "path", "description": "The identifier for the Notion page to be updated.", "schema": {"type": "string"}, "required": true}, {"$ref": "#/components/parameters/notionVersion"}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"properties": {"description": "The property values to update for the page. The keys are the names or IDs of the property and the values are property values. If a page property ID is not included, then it is not changed.", "type": "object", "additionalProperties": true}, "in_trash": {"type": "boolean", "description": "Set to true to delete a block. Set to false to restore a block.", "default": false}, "archived": {"type": "boolean"}, "icon": {"description": "A page icon for the page. Supported types are [external file object](https://developers.notion.com/reference/file-object) or [emoji object](https://developers.notion.com/reference/emoji-object).", "type": "object", "properties": {"emoji": {"type": "string"}}, "additionalProperties": false, "required": ["emoji"]}, "cover": {"type": "object", "description": "A cover image for the page. Only [external file objects](https://developers.notion.com/reference/file-object) are supported.", "properties": {"external": {"type": "object", "properties": {"url": {"type": "string"}}, "additionalProperties": false, "required": ["url"]}, "type": {"enum": ["external"], "type": "string"}}, "required": ["external"], "additionalProperties": false}}}}}}, "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/pages": {"post": {"summary": "Create a page", "description": "", "operationId": "post-page", "parameters": [{"$ref": "#/components/parameters/notionVersion"}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "required": ["parent", "properties"], "properties": {"parent": {"$ref": "#/components/schemas/parentRequest"}, "properties": {"description": "The property values for the new page. The keys are the names or IDs of the property and the values are property values.", "type": "object", "additionalProperties": true}, "children": {"type": "array", "description": "The content to be rendered on the new page, represented as an array of [block objects](https://developers.notion.com/reference/block).", "items": {"type": "string"}}, "icon": {"type": "string", "description": "The icon of the new page. Either an [emoji object](https://developers.notion.com/reference/emoji-object) or an [external file object](https://developers.notion.com/reference/file-object)..", "format": "json"}, "cover": {"type": "string", "description": "The cover image of the new page, represented as a [file object](https://developers.notion.com/reference/file-object).", "format": "json"}}}}}}, "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/pages/{page_id}/properties/{property_id}": {"get": {"summary": "Retrieve a page property item", "description": "", "operationId": "retrieve-a-page-property", "parameters": [{"name": "page_id", "in": "path", "description": "Identifier for a Notion page", "schema": {"type": "string"}, "required": true}, {"name": "property_id", "in": "path", "description": "Identifier for a page [property](https://developers.notion.com/reference/page#all-property-values)", "schema": {"type": "string"}, "required": true}, {"name": "page_size", "in": "query", "description": "For paginated properties. The max number of property item objects on a page. The default size is 100", "schema": {"type": "integer", "format": "int32"}}, {"name": "start_cursor", "in": "query", "description": "For paginated properties.", "schema": {"type": "string"}}, {"$ref": "#/components/parameters/notionVersion"}], "responses": {"200": {"description": "200", "content": {"application/json": {"examples": {}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/comments": {"get": {"summary": "Retrieve comments", "description": "Retrieves a list of un-resolved [Comment objects](ref:comment-object) from a page or block.", "operationId": "retrieve-a-comment", "parameters": [{"name": "block_id", "in": "query", "description": "Identifier for a Notion block or page", "required": true, "schema": {"type": "string"}}, {"name": "start_cursor", "in": "query", "description": "If supplied, this endpoint will return a page of results starting after the cursor provided. If not supplied, this endpoint will return the first page of results.", "schema": {"type": "string"}}, {"name": "page_size", "in": "query", "description": "The number of items from the full list desired in the response. Maximum: 100", "schema": {"type": "integer", "format": "int32"}}, {"$ref": "#/components/parameters/notionVersion"}], "responses": {"200": {"description": "200", "content": {"application/json": {"examples": {"OK": {"value": {"object": "list", "results": [{"object": "comment", "id": "94cc56ab-9f02-409d-9f99-1037e9fe502f", "parent": {"type": "page_id", "page_id": "5c6a2821-6bb1-4a7e-b6e1-c50111515c3d"}, "discussion_id": "f1407351-36f5-4c49-a13c-49f8ba11776d", "created_time": "2022-07-15T16:52:00.000Z", "last_edited_time": "2022-07-15T19:16:00.000Z", "created_by": {"object": "user", "id": "9b15170a-9941-4297-8ee6-83fa7649a87a"}, "rich_text": [{"type": "text", "text": {"content": "Single comment", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Single comment", "href": null}]}], "next_cursor": null, "has_more": false, "type": "comment", "comment": {}}}}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}, "post": {"summary": "Create comment", "description": "Creates a comment in a page or existing discussion thread.", "operationId": "create-a-comment", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "required": ["parent", "rich_text"], "properties": {"parent": {"type": "object", "description": "The page that contains the comment", "required": ["page_id"], "properties": {"page_id": {"type": "string", "description": "the page ID"}}}, "rich_text": {"type": "array", "items": {"type": "object", "required": ["text"], "properties": {"text": {"type": "object", "required": ["content"], "properties": {"content": {"type": "string", "description": "The content of the comment"}}}}}}}}}}}, "responses": {"200": {"description": "200", "content": {"application/json": {"examples": {"Result": {"value": {"object": "comment", "id": "b52b8ed6-e029-4707-a671-832549c09de3", "parent": {"type": "page_id", "page_id": "5c6a2821-6bb1-4a7e-b6e1-c50111515c3d"}, "discussion_id": "f1407351-36f5-4c49-a13c-49f8ba11776d", "created_time": "2022-07-15T20:53:00.000Z", "last_edited_time": "2022-07-15T20:53:00.000Z", "created_by": {"object": "user", "id": "067dee40-6ebd-496f-b446-093c715fb5ec"}, "rich_text": [{"type": "text", "text": {"content": "Hello world", "link": null}, "annotations": {"bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default"}, "plain_text": "Hello world", "href": null}]}}}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/data_sources/{data_source_id}/query": {"post": {"summary": "Query a data source", "description": "Query a data source (database) using filters and sorts", "operationId": "query-data-source", "tags": ["Data sources"], "parameters": [{"name": "data_source_id", "in": "path", "description": "Identifier for a Notion data source (database)", "schema": {"type": "string"}, "required": true}, {"name": "filter_properties", "in": "query", "description": "A list of page property value IDs to limit the response", "schema": {"type": "array", "items": {"type": "string"}}}, {"$ref": "#/components/parameters/notionVersion"}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"filter": {"type": "object", "description": "Filter conditions for querying the data source"}, "sorts": {"type": "array", "items": {"$ref": "#/components/schemas/sortObject"}}, "start_cursor": {"type": "string"}, "page_size": {"type": "integer", "default": 100}, "archived": {"type": "boolean"}, "in_trash": {"type": "boolean"}}}}}}, "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/data_sources/{data_source_id}": {"get": {"summary": "Retrieve a data source", "description": "Retrieve metadata and schema for a data source", "operationId": "retrieve-a-data-source", "tags": ["Data sources"], "parameters": [{"name": "data_source_id", "in": "path", "description": "Identifier for a Notion data source", "schema": {"type": "string"}, "required": true}, {"$ref": "#/components/parameters/notionVersion"}], "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}, "patch": {"summary": "Update a data source", "description": "Update properties of a data source", "operationId": "update-a-data-source", "tags": ["Data sources"], "parameters": [{"name": "data_source_id", "in": "path", "description": "Identifier for a Notion data source", "schema": {"type": "string"}, "required": true}, {"$ref": "#/components/parameters/notionVersion"}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"title": {"type": "array", "items": {"$ref": "#/components/schemas/richTextRequest"}}, "description": {"type": "array", "items": {"$ref": "#/components/schemas/richTextRequest"}, "maxItems": 100}, "properties": {"type": "object", "description": "Property schema updates"}}}}}}, "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/data_sources": {"post": {"summary": "Create a data source", "description": "Create a new data source (database)", "operationId": "create-a-data-source", "tags": ["Data sources"], "parameters": [{"$ref": "#/components/parameters/notionVersion"}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "required": ["parent", "properties"], "properties": {"parent": {"$ref": "#/components/schemas/pageIdParentRequest"}, "properties": {"type": "object", "description": "Property schema of data source"}, "title": {"type": "array", "items": {"$ref": "#/components/schemas/richTextRequest"}, "maxItems": 100}}}}}}, "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/data_sources/{data_source_id}/templates": {"get": {"summary": "List templates in a data source", "description": "List available templates for a data source", "operationId": "list-data-source-templates", "tags": ["Data sources"], "parameters": [{"name": "data_source_id", "in": "path", "description": "Identifier for a Notion data source", "schema": {"type": "string"}, "required": true}, {"name": "start_cursor", "in": "query", "schema": {"type": "string"}}, {"name": "page_size", "in": "query", "schema": {"type": "integer", "default": 100}}, {"$ref": "#/components/parameters/notionVersion"}], "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/databases/{database_id}": {"get": {"summary": "Retrieve a database", "description": "Retrieves a database object using the ID specified. Returns database metadata including the list of data source IDs contained in the database.", "operationId": "retrieve-a-database", "tags": ["Databases"], "parameters": [{"name": "database_id", "in": "path", "description": "Identifier for a Notion database", "schema": {"type": "string"}, "required": true}, {"$ref": "#/components/parameters/notionVersion"}], "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}, "/v1/pages/{page_id}/move": {"post": {"summary": "Move a page", "description": "Move a page to a different parent location", "operationId": "move-page", "tags": ["Pages"], "parameters": [{"name": "page_id", "in": "path", "description": "Identifier for a Notion page", "schema": {"type": "string", "format": "uuid"}, "required": true}, {"$ref": "#/components/parameters/notionVersion"}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "required": ["parent"], "properties": {"parent": {"$ref": "#/components/schemas/movePageParentRequest"}}}}}}, "responses": {"200": {"description": "Successful response", "content": {"application/json": {"schema": {"type": "object"}}}}, "400": {"description": "Bad request", "content": {"application/json": {"schema": {"type": "object", "properties": {"object": {"type": "string", "example": "error"}, "status": {"type": "integer", "example": 400}, "code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "deprecated": false, "security": []}}}} \ No newline at end of file