This document describes the HTTP API exposed by the LittleBoatPoll backend (bot + dashboard).
- Base path:
/api - JSON body:
application/jsonfor most endpoints - Dashboard routes require a valid
dashboard.sidsession cookie and Discord OAuth session. - Error responses use JSON:
{ "success": false, "error": "..." }(dashboard commands) or{ "error": "..." }for auth routes.
- Method:
GET - Path:
/api/health - Auth: none
- Response:
200textBot Online! [ENV]
- Method:
GET - Path:
/api/auth/discord/login - Auth: none
- Response: HTTP redirect to Discord OAuth URL
- Errors:
500when OAuth config is missing (JSON containsmissingarray)
- Method:
GET - Path:
/api/auth/discord/callback - Auth: none
- Response: HTTP redirect to dashboard frontend with
?auth=query parameter - Errors: redirect with
?auth=invalid_state|forbidden|error
- Method:
GET - Path:
/api/auth/me - Auth: session cookie
- Response:
200JSON{ "authenticated": true, "user": { ... } }
- Errors:
401,403with JSON{ "error": "...", "authenticated": false }
- Method:
GET - Path:
/api/auth/guilds - Auth: session cookie
- Response:
200JSON:{ "guilds": [ { id,name,icon,isActive }, ... ] }
- Method:
GET - Path:
/api/auth/guilds/:guildId/members - Query:
queryoptional text filter - Auth: session cookie
- Response:
200JSON:{ "members": [ ... ] } - Errors:
403,404,500
- Method:
GET - Path:
/api/auth/guilds/:guildId/channels - Auth: session cookie
- Response:
200JSON:{ "channels": [ ... ] } - Errors:
403,404,500
- Method:
GET - Path:
/api/auth/guilds/:guildId/group-members - Query:
group=mensalistas|criadores - Auth: session cookie
- Response:
200JSON:{ "ids": [ ... ] } - Errors:
400,403,500
- Method:
POST - Path:
/api/auth/logout - Auth: session cookie
- Response:
200JSON:{ "success": true }
- Method:
GET - Path:
/api/commands/catalog - Auth: session cookie
- Response:
200JSON:{ "success": true, "message": "...", "commands": [ ... ] }
- Method:
GET - Path:
/api/commands/context-targets/polls - Query:
guildIdoptional - Auth: session cookie
- Response:
200JSON:{ "success": true, "message": "...", "polls": [ ... ] }
- Method:
GET - Path:
/api/commands/context-targets/drafts - Auth: session cookie
- Response:
200JSON:{ "success": true, "message": "...", "drafts": [ ... ] }
- Method:
POST - Path:
/api/commands/:commandName - Auth: session cookie
- Body example:
{
"options": { ... },
"guild": { "id": "..." },
"commandType": 1,
"target": { "channelId": "..." }
}- Success:
200JSON{ "success": true, "message": "..." } - Errors:
400invalid type or payload403unauthorized guild404command not found / guild not connected429command locked503bot offline500internal error
POST /api/commands/rascunhowith subcommandcriaracceptsoptions.values.duracao.- Allowed values:
1h,6h,12h,24h,3d,7d. - If omitted, backend defaults to
24hfor dashboard-created drafts. - On
rascunho publicar, backend computesendsAtin UTC ISO and persists it with the active poll record. - Active poll lifecycle:
status: ativawhilenow < endsAt- auto-close when
now >= endsAt - result is persisted in history with
status: ended,dataFinalizacao,endsAt,durationKey,closeReason
- Auto-close execution:
- periodic scheduler every 30 seconds
- startup sweep after reaction sync to close already expired polls
- close path is idempotent to avoid double-close races with manual context command
- Method:
POST - Path:
/api/csv/upload - Auth: session cookie
- Content type:
multipart/form-data - Form field:
file(CSV file) CSVparser expects semicolon delimiter:nome-da-enquete;opcoes;max_votos;peso_mensalistas- Success:
200JSON with result from upload controller - Errors:
400,413file too big,500internal
- All routes log errors either in console (initial boot) or through structured logger in production.
- Dashboard controller responses use
{ "success": false, "error": "..." }.
docs/development/SETUP.md(environment and commands)docs/development/ARCHITECTURE.md(overall architecture)dashboard/README.md(dashboard domain details)
- Method:
GET - Path:
/api/polls/:pollId - Auth: dashboard session
- Response:
200JSON{ "success": true, "poll": { ... } }
The poll detail payload may include analytics fields for active and ended polls:
-
participants: an array of participant objects when available. Each participant object contains:userId: stringusername: string | null (may be null for anonymous votes)displayName: string | null (may be null for anonymous votes)isMensalista: booleanchoices: string[] (list of emoji identifiers the user voted for)timestamp: ISO datetime string | null
-
totalParticipants: integer, the number of unique userIds who voted in the poll. -
totalMensalistas: integer, the number of mensalistas among participants.
Note: For polls marked anonymous, participant names are redacted according to privacy flags. The API exposes participants, totalParticipants and totalMensalistas when available; when enrichment is not possible the endpoint may return an empty participants array and appropriate totals according to stored data.