{
  "openapi": "3.1.0",
  "info": {
    "title": "ChatDardsha public endpoints",
    "version": "1.0.0",
    "description": "شات دردشة — Arabic-first anonymous chat. This document covers ONLY the small, unauthenticated, read-only surface that is intentionally public. The rest of the app's HTTP surface is a private backend for its own web and Android clients, gated by a device-bound session token, and is deliberately not documented here: it is not a general-purpose API and is not intended for third-party or agent use. There is no public write API, no API key issuance, and no sandbox. For what the product is and when an agent should point a person at it, see /llms.txt. VERSIONING: every endpoint answers on /api/v1/… and on its bare path; responses carry Api-Version, and a client may send the same header to pin the contract it was written against (an unknown value is ignored, never rejected). A path scheduled for removal answers with Deprecation and Sunset headers (RFC 8594 / RFC 9745) for at least 180 days first, and a breaking response change gets a new version rather than a silent edit. RATE LIMITS: 120 requests per 60s, advertised in RateLimit-Limit/-Reset/-Policy, with Retry-After on a 429. Full detail at https://chatdardsha.com/docs.",
    "contact": {
      "email": "chat@chatdardsha.com",
      "url": "https://chatdardsha.com/contact"
    }
  },
  "servers": [
    {
      "url": "https://chatdardsha.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/v1/stats/online": {
      "get": {
        "operationId": "getOnlineCount",
        "summary": "How many people are using the app right now",
        "description": "Count of users active in the last 7 minutes, app-wide. Read-only, unauthenticated, no personal data — the same number the site shows in its «متصل الآن» pill.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The current online count.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Api-Version": {
                "$ref": "#/components/headers/Api-Version"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnlineCount"
                },
                "example": {
                  "online": 38
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/edge-health": {
      "get": {
        "operationId": "getEdgeHealth",
        "summary": "Liveness of the edge Worker",
        "description": "Read-only health probe. Returns ok:true when the Worker is serving.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The Worker is serving.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Api-Version": {
                "$ref": "#/components/headers/Api-Version"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EdgeHealth"
                },
                "example": {
                  "ok": true,
                  "service": "chatdardsha-edge"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/online": {
      "get": {
        "operationId": "getOnlineCountUnversioned",
        "summary": "How many people are using the app right now",
        "description": "Count of users active in the last 7 minutes, app-wide. Read-only, unauthenticated, no personal data — the same number the site shows in its «متصل الآن» pill. Permanent unversioned alias of /api/v1/stats/online.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The current online count.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Api-Version": {
                "$ref": "#/components/headers/Api-Version"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnlineCount"
                },
                "example": {
                  "online": 38
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/edge-health": {
      "get": {
        "operationId": "getEdgeHealthUnversioned",
        "summary": "Liveness of the edge Worker",
        "description": "Read-only health probe. Returns ok:true when the Worker is serving. Permanent unversioned alias of /api/v1/edge-health.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The Worker is serving.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Api-Version": {
                "$ref": "#/components/headers/Api-Version"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EdgeHealth"
                },
                "example": {
                  "ok": true,
                  "service": "chatdardsha-edge"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "ApiVersion": {
        "name": "Api-Version",
        "in": "header",
        "required": false,
        "description": "The contract this client was written against, as a date (e.g. 2026-08-25). Echoed back on every response. An unrecognised value is IGNORED rather than rejected, so pinning can never break a working client.",
        "schema": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        }
      }
    },
    "headers": {
      "RateLimit-Limit": {
        "description": "Requests allowed per window on the documented endpoints.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Reset": {
        "description": "Seconds until the window resets.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Policy": {
        "description": "The quota policy, e.g. 120;w=60.",
        "schema": {
          "type": "string"
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying. Present on 429.",
        "schema": {
          "type": "integer"
        }
      },
      "Api-Version": {
        "description": "The contract version that served this response.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "RateLimited": {
        "description": "Over the documented budget. Retry after the stated delay.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "ok": false,
              "error": "rate_limited",
              "message": "Over 120 requests per 60s. See https://chatdardsha.com/docs."
            }
          }
        }
      },
      "NotFound": {
        "description": "No such endpoint.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "ok": false,
              "error": "not_found"
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "Wrong HTTP method for this path.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "ok": false,
              "error": "method_not_allowed"
            }
          }
        }
      },
      "ServerError": {
        "description": "Unexpected failure. Same error shape as every other status.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "ok": false,
              "error": "internal_error"
            }
          }
        }
      }
    },
    "schemas": {
      "OnlineCount": {
        "type": "object",
        "title": "OnlineCount",
        "required": [
          "online"
        ],
        "properties": {
          "online": {
            "type": "integer",
            "minimum": 0,
            "description": "Users active in the last 7 minutes."
          }
        }
      },
      "EdgeHealth": {
        "type": "object",
        "title": "EdgeHealth",
        "required": [
          "ok",
          "service"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "True when the Worker is serving."
          },
          "service": {
            "type": "string",
            "description": "Service identifier."
          }
        }
      },
      "Error": {
        "type": "object",
        "title": "Error",
        "required": [
          "ok",
          "error"
        ],
        "description": "The shape every JSON error in this app uses, documented so an agent can parse a failure from any endpoint, including the ones not listed above.",
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "string",
            "description": "Stable machine-readable code.",
            "examples": [
              "unauthorized",
              "method_not_allowed",
              "not_found",
              "rate_limited"
            ]
          },
          "message": {
            "type": "string",
            "description": "Human-readable Arabic or English detail, when present."
          }
        }
      }
    }
  }
}