FrogTalk API Reference

Complete API Reference

All user-callable API endpoints currently in this codebase, including developer token API and federation update commands.

Base URL: https://your-host/api Β· Session header: X-Session-Token Β· Developer header: X-API-Key or Authorization: Bearer KEY

Auth Endpoints

PREFIX /api/auth
POST   /api/auth/register
POST   /api/auth/login
POST   /api/auth/logout
PATCH  /api/auth/nickname
GET    /api/auth/me
PATCH  /api/auth/profile
DELETE /api/auth/account
GET    /api/auth/captcha
POST   /api/auth/register-secure
POST   /api/auth/recovery-key
POST   /api/auth/recover
POST   /api/auth/verify-recovery-key
POST   /api/auth/federation-ticket
POST   /api/auth/federation-ticket-login

Users + Friends

PREFIX /api/users and /api/friends
GET    /api/users
GET    /api/users/{user_id}
POST   /api/users/{user_id}/block
DELETE /api/users/{user_id}/block
GET    /api/users/me/blocked
GET    /api/users/me/bans
GET    /api/users/{user_id}/aliases

GET    /api/users/search
GET    /api/users/profile/{nickname}
GET    /api/users/me/tags
POST   /api/users/me/tags
DELETE /api/users/me/tags/{tag}
POST   /api/users/me/presence

POST   /api/friends/request/{nickname}
POST   /api/friends/accept/{nickname}
POST   /api/friends/decline/{nickname}
DELETE /api/friends/{nickname}
POST   /api/friends/block/{nickname}
GET    /api/friends

Rooms, Messages, DMs

PREFIX /api/rooms, /api/messages, /api/dms
GET    /api/rooms
POST   /api/rooms
DELETE /api/rooms/{room_name}
GET    /api/rooms/{room_name}
PATCH  /api/rooms/{room_name}
POST   /api/rooms/{room_name}/moderators
DELETE /api/rooms/{room_name}/moderators/{user_id}
POST   /api/rooms/{room_name}/bans
DELETE /api/rooms/{room_name}/bans/{user_id}
GET    /api/rooms/{room_name}/bans
GET    /api/rooms/{room_name}/pins
POST   /api/rooms/{room_name}/pins/{msg_id}
DELETE /api/rooms/{room_name}/pins/{msg_id}
POST   /api/rooms/{room_name}/join
GET    /api/rooms/{room_name}/members
GET    /api/rooms/{room_name}/voice-participants
POST   /api/rooms/{room_name}/leave
GET    /api/rooms/{room_name}/queue
POST   /api/rooms/{room_name}/queue
DELETE /api/rooms/{room_name}/queue/{track_id}
POST   /api/rooms/{room_name}/queue/skip
POST   /api/rooms/{room_name}/queue/clear
POST   /api/rooms/{room_name}/dj-only
POST   /api/rooms/{room_name}/djs
DELETE /api/rooms/{room_name}/djs/{user_id}

POST   /api/messages/{room_name}/send
GET    /api/messages/media/{msg_id}
GET    /api/messages/{room_name}
PATCH  /api/messages/{msg_id}
DELETE /api/messages/{msg_id}
POST   /api/messages/{msg_id}/react
POST   /api/messages/{msg_id}/view
GET    /api/messages/search/global
GET    /api/messages/{room_name}/search
GET    /api/messages/users/mentionable

POST   /api/dms/open/{nickname}
GET    /api/dms
POST   /api/dms/{channel_id}/read
GET    /api/dms/{channel_id}/messages
GET    /api/dms/{channel_id}/messages/{msg_id}/media
POST   /api/dms/{channel_id}/messages
POST   /api/dms/{channel_id}/messages/{msg_id}/view
PUT    /api/dms/{channel_id}/messages/{msg_id}
DELETE /api/dms/{channel_id}/messages/{msg_id}
POST   /api/dms/{channel_id}/messages/{msg_id}/react
GET    /api/dms/{channel_id}/disappear
POST   /api/dms/{channel_id}/disappear
POST   /api/dms/{channel_id}/hide
POST   /api/dms/{channel_id}/unhide
DELETE /api/dms/{channel_id}/messages

Media, Emojis, Preview, Push, Calls, Location

GET    /api/emojis
POST   /api/emojis
DELETE /api/emojis/{emoji_id}

GET    /api/preview

GET    /api/push/vapid-key
POST   /api/push/subscribe
DELETE /api/push/unsubscribe
POST   /api/push/fcm-subscribe
DELETE /api/push/fcm-unsubscribe

GET    /api/calls/{call_id}/pending
GET    /api/calls/pending-latest
POST   /api/calls/{call_id}/decline
POST   /api/calls/decline

POST   /api/location/share
GET    /api/location/dm/{channel_id}
DELETE /api/location/dm/{channel_id}
PATCH  /api/location/settings

GET    /api/media/gifs/search
GET    /api/media/gifs/trending
GET    /api/media/gifs/categories
GET    /api/media/stickers/packs
POST   /api/media/stickers/packs
POST   /api/media/stickers
GET    /api/media/stickers/packs/{pack_id}
POST   /api/media/stickers/packs/{pack_id}/install
DELETE /api/media/stickers/packs/{pack_id}/uninstall
DELETE /api/media/stickers/{sticker_id}
GET    /api/media/stickers/public

Social, Wall, Directory, Invites

POST   /api/social/follow/{nickname}
DELETE /api/social/follow/{nickname}
GET    /api/social/profile/{nickname}
GET    /api/social/profile/{nickname}/posts
GET    /api/social/profile/{nickname}/followers
GET    /api/social/profile/{nickname}/channels
GET    /api/social/profile/{nickname}/following
GET    /api/social/feed
GET    /api/social/explore
GET    /api/social/suggested
GET    /api/social/profile/{nickname}/media
POST   /api/social/profile/media/{msg_id}/to-wall
GET    /api/social/stories
POST   /api/social/stories
POST   /api/social/stories/upload
POST   /api/social/stories/{story_id}/view
DELETE /api/social/stories/{story_id}
GET    /api/social/stories/{story_id}/viewers

GET    /api/wall/users/{username}
POST   /api/wall/posts
GET    /api/wall/posts/{post_id}
PUT    /api/wall/posts/{post_id}
DELETE /api/wall/posts/{post_id}
POST   /api/wall/posts/{post_id}/reactions
GET    /api/wall/posts/{post_id}/reactions
GET    /api/wall/posts/{post_id}/comments
POST   /api/wall/posts/{post_id}/comments
DELETE /api/wall/comments/{comment_id}
PATCH  /api/wall/settings
GET    /api/wall/settings

GET    /api/directory/channels
GET    /api/directory/channels/search
GET    /api/directory/categories
PATCH  /api/directory/channels/{room_name}/visibility
GET    /api/directory/featured
GET    /api/directory/suggested
GET    /api/directory/users/search
GET    /api/directory/channels/{room_name}/profile
POST   /api/directory/channels/{room_name}/like
DELETE /api/directory/channels/{room_name}/like
GET    /api/directory/channels/{room_name}/comments
POST   /api/directory/channels/{room_name}/comments
DELETE /api/directory/channels/{room_name}/comments/{comment_id}
PUT    /api/directory/channels/{room_name}/listing
GET    /api/directory/suggest
GET    /api/directory/new

POST   /api/invites/channels/{room_name}
GET    /api/invites/channels/{room_name}
DELETE /api/invites/channels/{room_name}/{code}
GET    /api/invites/{code}
POST   /api/invites/{code}/join
GET    /api/invites/{code}/landing

Developer + Bot Management

PREFIX /api/developer
POST   /api/developer/keys
GET    /api/developer/keys
DELETE /api/developer/keys/{key_id}
POST   /api/developer/bots
GET    /api/developer/bots
PUT    /api/developer/bots/{bot_id}
DELETE /api/developer/bots/{bot_id}
POST   /api/developer/channels/{room_name}/bots/{bot_id}
DELETE /api/developer/channels/{room_name}/bots/{bot_id}
GET    /api/developer/channels/{room_name}/bots
GET    /api/developer/bots/public

Use these endpoints to mint API keys and manage bot accounts/channels from your own backend tools.

Building a Bot πŸ€–

A FrogTalk bot is any program that holds a bot_… API key and calls the External Token API. Bots run anywhere β€” your laptop, a VPS, a serverless function β€” they only need outbound HTTP to your FrogTalk server. Every message a bot posts is stamped is_bot: true on the wire, so clients render a BOT pill next to the author name in chat. There is no way to disguise a bot as a human.

1. Create the bot

  1. Open Settings β†’ Developer β†’ Bots in the FrogTalk app.
  2. Click + Create Bot and pick a unique handle. This handle is the name users will @-mention.
  3. Copy the bot_… token shown in the dialog β€” it's only displayed once.
  4. Click Edit on the bot row to set its avatar, description, and whether it appears in the public directory (botfather-style).

2. Authenticate

Send the bot token on every request:

X-API-Key: bot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# or
Authorization: Bearer bot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

3. Poll for messages

Bots cannot open a WebSocket β€” they poll. Keep track of the highest message id you've seen, and act on anything newer:

import requests, time

BOT_TOKEN = "bot_…"
CHANNEL   = "general"
SERVER    = "https://frogtalk.xyz"

last_seen = 0
while True:
    r = requests.get(
        f"{SERVER}/api/external/channels/{CHANNEL}/messages",
        headers={"X-API-Key": BOT_TOKEN},
        params={"limit": 50},
        timeout=15,
    )
    for m in r.json()["messages"]:
        if m["id"] <= last_seen:
            continue
        last_seen = max(last_seen, m["id"])
        # … your logic …
    time.sleep(2)

4. Reply

requests.post(
    f"{SERVER}/api/external/channels/{CHANNEL}/messages",
    headers={"X-API-Key": BOT_TOKEN},
    json={"content": "hello, world!", "reply_to": m["id"]},
    timeout=15,
)

Setting reply_to threads the bot's reply under the trigger message so users see the quoted parent.

5. Profile (botfather-style)

PUT /api/developer/bots/{bot_id} updates the bot's profile. Uses your user session (not the bot key), so typically you'll use the in-app Edit dialog.

FieldTypeNotes
namestringunique handle (≀32 chars)
avatarstringURL or data: URL
descriptionstringshown in the directory (≀500 chars)
is_publicboollist publicly

Etiquette & limits

  • Rate limit: POST /channels/{name}/messages is capped at 30 req/min per bot key. Stay well under it.
  • No mention spam: only reply when the bot is explicitly addressed (an @mention in the message text, or a reply_to pointing at one of your own messages).
  • Don't impersonate: the BOT pill cannot be hidden.
  • Be transparent: set a useful description so users understand what data your bot processes.

Examples & SDK

Complete, runnable reference bots live in the FrogTalk repo under bot-examples/. Clone the repo, drop in your bot_… token, and run.

πŸ€– runpod-ai-bot — AI chat bot (Python)

A mention-driven AI chat bot powered by a RunPod serverless LLM endpoint. Polls public channels, replies when @-mentioned or when a user replies to its own message. ~200 lines, no async framework required. Sends the conversation to the worker as an OpenAI-style messages=[…] list so the vLLM worker applies the model's own chat template — swap in any modern instruct model (Qwen, Mistral-Small / MythoMax, Llama-3, etc.) with no code changes. Default endpoint runs Gryphe/MythoMax-L2-13b (uncensored Llama-2 roleplay finetune). Auto-falls-back to a raw Alpaca-style prompt if the worker reports the loaded model has no chat template registered. Includes a refusal-detection retry that catches canned RLHF safety output and re-rolls at higher temperature with a stronger jailbreak preface.

πŸš€ Quick start (60 seconds)

git clone https://github.com/deadinternetfox/frogtalk.git
cd frogtalk/bot-examples/runpod-ai-bot

# 1. Install deps
pip install -r requirements.txt

# 2. Configure
cp .env.example .env
$EDITOR .env   # paste your FROGTALK_BOT_TOKEN and RUNPOD_* values

# 3. Run
python bot.py

πŸ§ͺ Minimal bot in 20 lines

Don't want the full example? Here's the smallest useful loop — reads new messages from a channel and replies to mentions:

import os, time, requests

TOKEN   = os.environ["FROGTALK_BOT_TOKEN"]    # bot_xxx from /api/developer/bots
BASE    = "https://frogtalk.xyz/api/external"
CHANNEL = "general"
HEADERS = {"X-API-Key": TOKEN}
seen = set()

while True:
    r = requests.get(f"{BASE}/channels/{CHANNEL}/messages?limit=20", headers=HEADERS, timeout=10)
    for m in r.json().get("messages", []):
        if m["id"] in seen: continue
        seen.add(m["id"])
        if "@mybot" in (m.get("text") or "").lower():
            requests.post(
                f"{BASE}/channels/{CHANNEL}/messages",
                headers=HEADERS,
                json={"text": f"hi @{m['nickname']} πŸ‘‹", "reply_to": m["id"]},
                timeout=10,
            )
    time.sleep(5)

🟦 TypeScript / Node.js

const TOKEN   = process.env.FROGTALK_BOT_TOKEN!;
const BASE    = "https://frogtalk.xyz/api/external";
const CHANNEL = "general";
const headers = { "X-API-Key": TOKEN, "Content-Type": "application/json" };
const seen = new Set<number>();

async function tick() {
  const r = await fetch(`${BASE}/channels/${CHANNEL}/messages?limit=20`, { headers });
  const { messages = [] } = await r.json();
  for (const m of messages) {
    if (seen.has(m.id)) continue;
    seen.add(m.id);
    if ((m.text || "").toLowerCase().includes("@mybot")) {
      await fetch(`${BASE}/channels/${CHANNEL}/messages`, {
        method: "POST", headers,
        body: JSON.stringify({ text: `hi @${m.nickname} πŸ‘‹`, reply_to: m.id }),
      });
    }
  }
}
setInterval(tick, 5000);

Want to contribute another reference bot (TypeScript, Go, Rust, a Discord-style command bot, an RSS poster…)? Open a PR against bot-examples/.

External Token API (for Devs and Bots)

PREFIX /api/external

Auth: X-API-Key: frog_xxx or Authorization: Bearer frog_xxx. Key comes from /api/developer/keys.

GET    /api/external/docs
GET    /api/external/health
GET    /api/external/me
GET    /api/external/me/channels
GET    /api/external/channels
GET    /api/external/channels/{name}/messages
POST   /api/external/channels/{name}/messages
GET    /api/external/users/{user_id}
POST   /api/external/dms/{user_id}
POST   /api/external/webhooks
curl -X GET https://frogtalk.xyz/api/external/me \
  -H "X-API-Key: frog_your_key_here"

Bot keys only: GET /api/external/me/channels returns the list of channels the bot has been installed in (via Settings β†’ Bots β†’ Add to channel). Auto-discovery clients should poll this every ~30s instead of hardcoding a channel list.

Bridge API (Discord / Telegram)

PREFIX /api
GET    /api/bridges
GET    /api/rooms/{room_name}/bridge-outbound
POST   /api/bridges/create
POST   /api/bridges/prepare-code
GET    /api/bridges/check-code/{code}
POST   /api/bridges/claim-code
DELETE /api/bridges/{bridge_id}
POST   /api/bridges/{bridge_id}/toggle
POST   /api/bridges/{bridge_id}/direction
GET    /api/discord-bridges
GET    /api/discord-bridges/invite-meta
POST   /api/discord-bridges/validate-channel
POST   /api/discord-bridges/create
DELETE /api/discord-bridges/{bridge_id}
POST   /api/bridge/message

Federation, Network, Trust, Updates

PREFIX /api
GET    /api/network/status
GET    /api/network/servers
GET    /api/network/probe
GET    /api/network/auto-select
GET    /api/network/build/local
POST   /api/network/build/verify-peers
GET    /api/network/updates/latest
POST   /api/network/updates/publish
GET    /api/network/update/status
POST   /api/network/update/check
POST   /api/network/update/apply
POST   /api/network/servers/register
POST   /api/network/servers/sync-official
GET    /api/network/status/tor
POST   /api/network/servers/register-transport

GET    /api/identity/me
PUT    /api/identity/me/pubkey
GET    /api/identity/me/claim
GET    /api/identity/users/{user_id}/claim

POST   /api/federation/events/inbox
POST   /api/federation/manifests/register
GET    /api/federation/manifests/verify
GET    /api/federation/manifests/list
POST   /api/federation/events/emit
GET    /api/federation/events/outbox
GET    /api/federation/failover/status

Admin + Server Admin

Server-sensitive endpoints.
POST   /api/admin/ban/{nickname}
POST   /api/admin/unban/{nickname}
POST   /api/admin/kick/{nickname}
POST   /api/admin/mute/{nickname}
POST   /api/admin/unmute/{nickname}

GET    /server
GET    /api/server-admin/config
GET    /api/server-admin/easter-egg
PUT    /api/server-admin/easter-egg
POST   /api/server-admin/easter-egg/upload
GET    /api/server/easter-egg
POST   /api/server-admin/login
POST   /api/server-admin/logout
GET    /api/server-admin/me
GET    /api/server-admin/stats
GET    /api/server-admin/online-users
GET    /api/server-admin/nodes
GET    /api/server-admin/nodes/{server_id}/probe
POST   /api/server-admin/nodes/{server_id}/block
POST   /api/server-admin/nodes/{server_id}/unblock
POST   /api/server-admin/control/sync-official-directory
POST   /api/server-admin/control/kick
POST   /api/server-admin/control/ban
POST   /api/server-admin/control/unban
POST   /api/server-admin/control/mute
POST   /api/server-admin/control/unmute

Misc + Real-time

GET    /api/ping
GET    /invite/{code}          (landing)
WebSocket: /ws/{room_name}?token=SESSION_TOKEN

This page now mirrors the current routed API surface in this repository.