{
  "openapi": "3.1.0",
  "info": {
    "title": "LiveReplays public API",
    "version": "1.0.0",
    "summary": "Anonymous, read-only endpoints for the LiveReplays platform.",
    "description": "Read-only endpoints that need no credential: platform health, floored platform counts, and the plan and price list. Every response is JSON and carries RFC 9331 rate-limit headers. The published limit is advisory: Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection. Errors are RFC 9457 problem details. Account data — libraries, recordings, clips — is not on this surface; it requires a bearer token and is described at https://api.livereplays.cc/openapi.json.",
    "contact": {
      "name": "LiveReplays support",
      "email": "support@livereplays.cc",
      "url": "https://livereplays.cc/support"
    },
    "termsOfService": "https://livereplays.cc/terms"
  },
  "servers": [
    {
      "url": "https://livereplays.cc",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "LiveReplays developer documentation",
    "url": "https://livereplays.cc/developers"
  },
  "tags": [
    {
      "name": "public",
      "description": "Anonymous, read-only endpoints."
    }
  ],
  "security": [],
  "paths": {
    "/api/public": {
      "get": {
        "operationId": "getPublicApiIndex",
        "summary": "List the anonymous endpoints",
        "description": "Service descriptor for the anonymous LiveReplays API: every endpoint, its operationId, and the documents that describe the surface. Fetch this first if you are discovering the API programmatically — it is stable and needs no credential.",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "List the anonymous endpoints",
            "headers": {
              "RateLimit": {
                "description": "RFC 9331 structured field, e.g. `limit=60, remaining=59, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The published policy, e.g. `\"public\"; q=60; w=60`. Advisory — Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "service": {
                      "type": "string",
                      "description": "Always \"LiveReplays public API\"."
                    },
                    "documentation": {
                      "type": "string",
                      "format": "uri",
                      "description": "Human-readable documentation."
                    },
                    "openapi": {
                      "type": "string",
                      "format": "uri",
                      "description": "OpenAPI 3.1 description of this surface."
                    },
                    "authentication": {
                      "type": "string",
                      "description": "Always \"none\" — every endpoint listed here is anonymous."
                    },
                    "rate_limit": {
                      "type": "object",
                      "description": "The published policy, matching the RateLimit-Policy header.",
                      "properties": {
                        "limit": {
                          "type": "integer",
                          "description": "Requests permitted per window."
                        },
                        "window_seconds": {
                          "type": "integer",
                          "description": "Window length in seconds."
                        },
                        "policy": {
                          "type": "string",
                          "description": "The RateLimit-Policy field value."
                        },
                        "enforcement": {
                          "type": "string",
                          "enum": [
                            "advisory"
                          ],
                          "description": "How the figure is applied. \"advisory\" means the counter is per server instance: the effective ceiling across the fleet is higher and resets when an instance is recycled."
                        },
                        "note": {
                          "type": "string",
                          "description": "The same caveat, as one sentence for a program."
                        }
                      },
                      "required": [
                        "limit",
                        "window_seconds",
                        "policy",
                        "enforcement",
                        "note"
                      ]
                    },
                    "endpoints": {
                      "type": "array",
                      "description": "Every anonymous endpoint on this surface.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "method": {
                            "type": "string",
                            "description": "HTTP method."
                          },
                          "url": {
                            "type": "string",
                            "format": "uri",
                            "description": "Absolute URL."
                          },
                          "operation_id": {
                            "type": "string",
                            "description": "Matches operationId in the OpenAPI document."
                          },
                          "summary": {
                            "type": "string",
                            "description": "What the endpoint returns."
                          }
                        },
                        "required": [
                          "method",
                          "url",
                          "operation_id",
                          "summary"
                        ]
                      }
                    }
                  },
                  "required": [
                    "service",
                    "documentation",
                    "openapi",
                    "authentication",
                    "rate_limit",
                    "endpoints"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait `Retry-After` seconds and retry.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit": {
                "description": "RFC 9331 structured field, e.g. `limit=60, remaining=59, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The published policy, e.g. `\"public\"; q=60; w=60`. Advisory — Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/status": {
      "get": {
        "operationId": "getPlatformStatus",
        "summary": "Current platform health",
        "description": "Live health of the LiveReplays platform: an overall state plus one entry per monitored component (API, database, background workers, recording engine). This is the same snapshot the /status page renders, so an agent answering \"is LiveReplays up?\" can read it directly instead of parsing HTML.",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Current platform health",
            "headers": {
              "RateLimit": {
                "description": "RFC 9331 structured field, e.g. `limit=60, remaining=59, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The published policy, e.g. `\"public\"; q=60; w=60`. Advisory — Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "operational",
                        "degraded",
                        "down",
                        "unknown"
                      ],
                      "description": "Worst state across all components. `unknown` means the snapshot could not be read just now — it is not a claim that the platform is healthy."
                    },
                    "components": {
                      "type": "object",
                      "description": "One entry per monitored subsystem, keyed by component id.",
                      "additionalProperties": {
                        "type": "object",
                        "description": "One monitored subsystem: its state and its name, nothing else.",
                        "properties": {
                          "status": {
                            "type": "string",
                            "enum": [
                              "operational",
                              "degraded",
                              "down",
                              "unknown"
                            ],
                            "description": "Current state of this component."
                          },
                          "name": {
                            "type": "string",
                            "description": "Human-readable component name."
                          }
                        },
                        "required": [
                          "status",
                          "name"
                        ]
                      }
                    },
                    "generated_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "When this snapshot was taken, RFC 3339."
                    }
                  },
                  "required": [
                    "status",
                    "components",
                    "generated_at"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait `Retry-After` seconds and retry.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit": {
                "description": "RFC 9331 structured field, e.g. `limit=60, remaining=59, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The published policy, e.g. `\"public\"; q=60; w=60`. Advisory — Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/pulse": {
      "get": {
        "operationId": "getPlatformPulse",
        "summary": "Platform scale, floored",
        "description": "Aggregate platform counts — replays archived, creators captured, captures in the trailing window. Every figure is floored to `step` before it leaves the backend, and a figure whose floored value lands in the bottom bucket is returned as null rather than as a zero, because a published zero is its own disclosure. No creator, recording or account is identifiable from this endpoint.",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Platform scale, floored",
            "headers": {
              "RateLimit": {
                "description": "RFC 9331 structured field, e.g. `limit=60, remaining=59, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The published policy, e.g. `\"public\"; q=60; w=60`. Advisory — Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "replays_archived": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Recordings in the catalogue, floored to `step`. Null when suppressed."
                    },
                    "creators_captured": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Distinct creators ever captured, floored to `step`. Null when suppressed."
                    },
                    "captures_7d": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Captures in the trailing `window_days`, floored to `step`. Null when suppressed."
                    },
                    "window_days": {
                      "type": "integer",
                      "description": "Length of the trailing window, in days."
                    },
                    "step": {
                      "type": "integer",
                      "description": "Bucket size every figure was floored to."
                    },
                    "generated_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "When this snapshot was taken, RFC 3339."
                    }
                  },
                  "required": [
                    "replays_archived",
                    "creators_captured",
                    "captures_7d",
                    "window_days",
                    "step"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait `Retry-After` seconds and retry.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit": {
                "description": "RFC 9331 structured field, e.g. `limit=60, remaining=59, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The published policy, e.g. `\"public\"; q=60; w=60`. Advisory — Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "The upstream snapshot was unreachable or answered with an unexpected shape.",
            "headers": {
              "RateLimit": {
                "description": "RFC 9331 structured field, e.g. `limit=60, remaining=59, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The published policy, e.g. `\"public\"; q=60; w=60`. Advisory — Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/plans": {
      "get": {
        "operationId": "getPlans",
        "summary": "Plans and prices",
        "description": "Every purchasable plan with its price, currency and billing period, plus the payment rails accepted. These are the same figures the pricing grid and the SoftwareApplication JSON-LD publish; they come from one constant, so this endpoint cannot quote a price checkout would not honour.",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Plans and prices",
            "headers": {
              "RateLimit": {
                "description": "RFC 9331 structured field, e.g. `limit=60, remaining=59, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The published policy, e.g. `\"public\"; q=60; w=60`. Advisory — Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "currency": {
                      "type": "string",
                      "description": "ISO 4217 code every amount below is denominated in."
                    },
                    "billing": {
                      "type": "string",
                      "description": "How a plan is bought. One-shot crypto invoices — there is no card-on-file recurring charge."
                    },
                    "payment_methods": {
                      "type": "array",
                      "description": "Accepted payment rails.",
                      "items": {
                        "type": "string"
                      }
                    },
                    "plans": {
                      "type": "array",
                      "description": "Every plan, free tier included.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Stable plan identifier."
                          },
                          "name": {
                            "type": "string",
                            "description": "Display name."
                          },
                          "amount": {
                            "type": "number",
                            "description": "Price in `currency`. 0 for the free tier."
                          },
                          "period": {
                            "type": "string",
                            "description": "Billing period the amount buys."
                          },
                          "days": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Days of Pro the amount buys, null for the free tier."
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "amount",
                          "period",
                          "days"
                        ]
                      }
                    }
                  },
                  "required": [
                    "currency",
                    "billing",
                    "payment_methods",
                    "plans"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait `Retry-After` seconds and retry.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit": {
                "description": "RFC 9331 structured field, e.g. `limit=60, remaining=59, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The published policy, e.g. `\"public\"; q=60; w=60`. Advisory — Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/openapi.json": {
      "get": {
        "operationId": "getOpenApiDocument",
        "summary": "OpenAPI 3.1 description of this API",
        "description": "The machine-readable description of every operation listed here, including response schemas and the rate-limit policy. Served as application/json so any OpenAPI tool can read it without a content-type override.",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 description of this API",
            "headers": {
              "RateLimit": {
                "description": "RFC 9331 structured field, e.g. `limit=60, remaining=59, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The published policy, e.g. `\"public\"; q=60; w=60`. Advisory — Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "An OpenAPI 3.1 document.",
                  "properties": {
                    "openapi": {
                      "type": "string",
                      "description": "Specification version, \"3.1.0\"."
                    },
                    "info": {
                      "type": "object",
                      "description": "Title, version and description of this API."
                    },
                    "paths": {
                      "type": "object",
                      "description": "One entry per operation."
                    }
                  },
                  "required": [
                    "openapi",
                    "info",
                    "paths"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Wait `Retry-After` seconds and retry.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit": {
                "description": "RFC 9331 structured field, e.g. `limit=60, remaining=59, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The published policy, e.g. `\"public\"; q=60; w=60`. Advisory — Guidance, not a hard boundary: the counter is per server instance, so the effective ceiling across the fleet is higher and it resets when an instance is recycled. Pace to the published figure; do not rely on it as protection.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details.",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "Identifies the problem type."
          },
          "title": {
            "type": "string",
            "description": "Short, human-readable summary."
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code."
          },
          "detail": {
            "type": "string",
            "description": "Explanation specific to this occurrence."
          }
        },
        "required": [
          "type",
          "title",
          "status"
        ]
      }
    },
    "securitySchemes": {}
  }
}
