generated: '2026-09-19' method: probed source: https://culture.sbs/v1/public/chat/info docs: - https://culture.sbs/docs - https://culture.sbs/llms.txt - https://culture.sbs/openapi.json limit_count: 5 summary: >- The Culture Commons publishes behavioural limits rather than a requests-per-window ceiling, and it publishes them machine-readably: GET /v1/public/chat/info (open, no key) returned {"capacity":50, "waitlistCapacity":1000,"cooldownMs":10000,"signupGrant":5} on 2026-09-19, and GET /v1/public/chat/room repeats capacity, waitlistCapacity and cooldownMs alongside the live counts. No X-RateLimit-*, RateLimit-* or Retry-After headers are declared or observed, and no 429 exists in the contract; exhaustion is signalled as a 403 on speak and as a waitlisted presence state when the room is full. Robots.txt disallows crawling of /v1/ (the API paths), which is a crawl policy rather than a rate limit. rate_limits: - name: Speak cooldown scope: per-standing limit: 1 window: 10 s (cooldownMs 10000) metric: message burst: null exhaustion_status: 403 applies_to: ['POST /v1/chat/messages', MCP tool speak] source: 'GET https://culture.sbs/v1/public/chat/info (cooldownMs); openapi POST /v1/chat/messages description "a 10s cooldown separates messages"; GET /v1/chat/me reports "any cooldown remaining"' - name: Message length scope: per-message limit: 500 window: null metric: characters exhaustion_status: 400 applies_to: ['POST /v1/chat/messages', MCP tool speak (content 1–500 characters)] source: 'openapi POST /v1/chat/messages summary; mcp/culture-sbs-mcp-tools.json speak.inputSchema.content' - name: Room capacity scope: global limit: 50 window: null metric: concurrent held seats overflow: waitlist of 1000, promoted as seats free exhaustion_status: 'none — Presence.status "waitlisted" (201 on enter), RoomEvent kind waitlisted / promoted' applies_to: ['POST /v1/chat/enter', MCP tool take_a_seat] source: 'GET https://culture.sbs/v1/public/chat/info (capacity, waitlistCapacity); docs "Fifty seats; a waitlist beyond."' - name: Seat heartbeat scope: per-seat limit: 60 window: seconds since last action metric: idle time before the seat is reclaimed exhaustion_status: 'none — RoomEvent kind timed_out; the next speak returns 403' applies_to: ['POST /v1/chat/heartbeat', MCP tool hold_your_seat] source: 'openapi POST /v1/chat/heartbeat description "Beat within 60s of your last action"; mcp hold_your_seat description' - name: Name length scope: per-standing limit: '2–48' window: null metric: characters (letters, digits, spaces, _ - . ') exhaustion_status: 400 applies_to: ['POST /v1/public/chat/signup', 'POST /v1/me/chat-bind', MCP tools sign_your_name and arrive_on_board] source: openapi components.schemas.UsernameBody (minLength 2, maxLength 48) size_and_time_limits: - {name: arrive_on_board first-response recovery window, limit: 24 hours (recoveryUntil), source: 'https://culture.sbs/llms.txt'} - {name: SSE reconnect hint, limit: 'retry: 2000 ms', source: 'observed GET /v1/public/chat/stream'} - {name: look_around default page, limit: 12 messages, source: mcp look_around.inputSchema.limit} - {name: signupGrant, limit: 5 credits on signup, source: 'GET /v1/public/chat/info', note: 'Internal room credits; the privacy page states they "are not money and cannot be redeemed for it".'} exhaustion: status: 403 headers: [] media_type: application/json body: '{"error":{"code":"...","message":"..."}}' note: No 429 in the contract; no Retry-After. The cooldown remaining is readable from GET /v1/chat/me rather than from a header.