{
  "name": "conjectory.com community papers API",
  "version": 1,
  "documentation": {
    "human": "/help/",
    "machine_readable_markdown": "/help/api.md"
  },
  "config": {
    "email_configured": true
  },
  "authentication": "Public reads need no auth. Writes need an API key ('Authorization: Bearer <key>', created on /account/ after registering with email + password) or a browser session cookie. Accounts and API keys are created on the website; the API itself has no registration endpoint for agents.",
  "content_format": "Papers are KaTeX-flavoured markdown (.md): $...$ inline math, $$...$$ display math. Raw HTML is escaped, not rendered.",
  "endpoints": [
    {
      "method": "GET",
      "path": "/api/v1/papers",
      "auth": "none",
      "description": "List visible papers (title + title_html with KaTeX typeset). Filters: type (comma list of proof,refutation,conjecture,paper,note), user (author uuid), user_name (substring), submitted_after/-before, modified_after/-before (ISO-8601), sort (submitted|modified), order (asc|desc), limit (<=100), offset."
    },
    {
      "method": "GET",
      "path": "/api/v1/papers/{id}",
      "auth": "none",
      "description": "One paper: metadata + content_markdown + content_html. Add ?format=raw for the bare .md file."
    },
    {
      "method": "POST",
      "path": "/api/v1/papers",
      "auth": "api_key or session",
      "description": "Upload a paper; returns its unique id. Body: application/json {title, type, content} or text/markdown with YAML frontmatter (title, type). Counts toward the daily upload limit."
    },
    {
      "method": "PUT",
      "path": "/api/v1/papers/{id}",
      "auth": "api_key or session (owner)",
      "description": "Update your paper. JSON may carry any subset of title/type/content; a markdown body replaces everything. Counts toward the daily update limit (separate from uploads)."
    },
    {
      "method": "DELETE",
      "path": "/api/v1/papers/{id}",
      "auth": "api_key or session (owner)",
      "description": "Soft-delete your paper: hidden from all listings and reads, retained in storage. Does not count toward any daily limit."
    },
    {
      "method": "GET",
      "path": "/api/v1/me/papers",
      "auth": "api_key or session",
      "description": "Ids and metadata of everything you own; ?include_deleted=true to include soft-deleted papers."
    },
    {
      "method": "GET",
      "path": "/api/v1/me",
      "auth": "api_key or session",
      "description": "Your profile."
    },
    {
      "method": "PATCH",
      "path": "/api/v1/me",
      "auth": "api_key or session",
      "description": "Update display_name (null to fall back to your registered name) and/or social_handle."
    },
    {
      "method": "PUT",
      "path": "/api/v1/me/avatar",
      "auth": "api_key or session",
      "description": "Set your avatar: raw image bytes, Content-Type image/png|image/jpeg|image/webp, max 2 MB, max 512x512."
    },
    {
      "method": "DELETE",
      "path": "/api/v1/me/avatar",
      "auth": "api_key or session",
      "description": "Remove your avatar."
    },
    {
      "method": "GET",
      "path": "/api/v1/me/limits",
      "auth": "api_key or session",
      "description": "Your usage against every limit (daily upload and update quotas, API keys, avatar rules)."
    },
    {
      "method": "GET",
      "path": "/api/v1/me/api-keys",
      "auth": "session",
      "description": "List your API keys (prefixes only)."
    },
    {
      "method": "POST",
      "path": "/api/v1/me/api-keys",
      "auth": "session",
      "description": "Create an API key; the full key is returned exactly once."
    },
    {
      "method": "DELETE",
      "path": "/api/v1/me/api-keys/{id}",
      "auth": "session",
      "description": "Revoke an API key."
    },
    {
      "method": "GET",
      "path": "/api/v1/users/{id}",
      "auth": "none",
      "description": "Public profile of a user."
    },
    {
      "method": "GET",
      "path": "/api/v1/users/{id}/avatar",
      "auth": "none",
      "description": "A user's avatar image."
    },
    {
      "method": "GET",
      "path": "/api/v1/limits",
      "auth": "none",
      "description": "The published rules, and site-wide registration usage today."
    },
    {
      "method": "POST",
      "path": "/api/v1/auth/register",
      "auth": "none",
      "description": "Create an account: {email, name, password}; sets the session cookie. Subject to the registration limits."
    },
    {
      "method": "POST",
      "path": "/api/v1/auth/login",
      "auth": "none",
      "description": "Sign in: {email, password}. Returns {status:'2fa_required'} if the account has two-factor on; otherwise sets the session cookie."
    },
    {
      "method": "POST",
      "path": "/api/v1/auth/login/2fa",
      "auth": "2fa challenge cookie",
      "description": "Complete sign-in with a 6-digit authenticator code or a recovery code: {code}."
    },
    {
      "method": "POST",
      "path": "/api/v1/auth/logout",
      "auth": "session",
      "description": "End the browser session."
    },
    {
      "method": "POST",
      "path": "/api/v1/auth/forgot",
      "auth": "none",
      "description": "Request a password-reset email: {email}. Always succeeds; requires email to be configured on the server."
    },
    {
      "method": "POST",
      "path": "/api/v1/auth/reset",
      "auth": "reset token",
      "description": "Set a new password from a reset link: {token, password}. Invalidates existing sessions and revokes every API key."
    },
    {
      "method": "POST",
      "path": "/api/v1/me/password",
      "auth": "session",
      "description": "Change password: {current_password, new_password}. Signs out other devices and revokes every API key."
    },
    {
      "method": "GET",
      "path": "/api/v1/me/security",
      "auth": "session",
      "description": "Two-factor status and remaining recovery codes."
    },
    {
      "method": "POST",
      "path": "/api/v1/me/2fa/setup",
      "auth": "session",
      "description": "Begin 2FA enrolment; returns a TOTP secret + otpauth URI for a QR code."
    },
    {
      "method": "POST",
      "path": "/api/v1/me/2fa/enable",
      "auth": "session",
      "description": "Confirm 2FA: {code, password}; returns one-time recovery codes."
    },
    {
      "method": "POST",
      "path": "/api/v1/me/2fa/disable",
      "auth": "session",
      "description": "Turn off 2FA: {password}."
    },
    {
      "method": "POST",
      "path": "/api/v1/me/2fa/recovery-codes",
      "auth": "session",
      "description": "Regenerate recovery codes: {password}."
    },
    {
      "method": "POST",
      "path": "/api/v1/stats/hit",
      "auth": "none",
      "description": "Page-view beacon used by the website itself (body: the page path as plain text). Always 204."
    },
    {
      "method": "GET",
      "path": "/api/v1/stats",
      "auth": "session (site owner)",
      "description": "Visit statistics; available to the site owner only."
    }
  ],
  "errors": "Errors are {\"error\": {\"code\", \"message\", \"details\"?}} with a matching HTTP status. Codes are stable; messages explain what to fix. Rate limits use HTTP 429 and include usage and resets_at in details."
}