June 18, 2026 · 10 min read

Como colocamos nossa retro semanal no piloto automático com a API do PollsLive

O passo a passo de uma desenvolvedora: criar uma enquete de retro, abrir uma sessão ao vivo e depois puxar resultados e um CSV - tudo a partir de um pequeno script Node num cron. Endpoints reais da /api/v1, payloads reais.

By Maya Okafor · Platform engineer·DevelopersHow-toTeams & meetings

Sou engenheira de plataforma e, toda sexta-feira, eu gastava dez minutos montando à mão o mesmo deck de retro. As mesmas cinco perguntas, semana diferente. Clássico caso de algo-que-um-script-deveria-fazer. Então passei tudo para a API do PollsLive e um cron job - agora a enquete se cria sozinha, uma sessão ao vivo abre automaticamente e, depois da daily, um CSV cai no nosso Slack. Aqui vai exatamente como, com os endpoints e payloads reais.

Tip

Você não precisa ser técnico para seguir este guia. Cada passo usa botões simples no PollsLive - sem código, sem instalar app para seu público.

Autenticação: um único token Bearer

Gerei uma chave de API do workspace em Studio → Developers (elas têm o formato `plv_live_…`) e a coloquei no ambiente do script. Toda requisição é só um token Bearer - sem dança de OAuth para uso servidor-a-servidor.

auth
# Base URL for all calls
export POLLSLIVE_API=https://pollslive.com/api/v1
export POLLSLIVE_KEY=plv_live_xxxxxxxxxxxxxxxxxxxx

# Every request carries the key as a Bearer token:
#   Authorization: Bearer $POLLSLIVE_KEY
# Rate limit: 120 requests/min per key (HTTP 429 if you exceed it).

Passo 1 - Criar a enquete de retro

Uma enquete é um deck tipado: `content.questions` é um array de slides, cada um com um discriminador `kind`. Para a retro eu uso uma scale, uma open_ended renderizada como nuvem e uma multiple_choice para votar na correção. Um `POST /polls` com `renderingMode: "LIVE"` me devolve um rascunho.

POST /polls
curl -sS -X POST "$POLLSLIVE_API/polls" \
  -H "Authorization: Bearer $POLLSLIVE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Weekly retro - week of Jun 16",
    "renderingMode": "LIVE",
    "content": {
      "questions": [
        {
          "id": "health",
          "kind": "scale",
          "text": "How healthy did this sprint feel?",
          "min": 1, "max": 5,
          "minLabel": "Rough", "maxLabel": "Great"
        },
        {
          "id": "blockers",
          "kind": "open_ended",
          "text": "What slowed us down this sprint?",
          "render": "cloud",
          "maxLength": 120
        },
        {
          "id": "fix",
          "kind": "multiple_choice",
          "type": "single",
          "text": "What should we fix first next sprint?",
          "options": [
            { "id": "ci",       "label": "Stabilise the CI pipeline" },
            { "id": "tickets",  "label": "Tighter ticket acceptance criteria" },
            { "id": "wip",      "label": "Cap WIP and reviews SLA" },
            { "id": "meetings", "label": "Trim the meeting load" }
          ]
        }
      ]
    }
  }'

A resposta `201` envolve a enquete num envelope `data` - guardo o `data.id` para o resto do fluxo e o `data.accessPin` / `data.shareUrl` para os detalhes de entrada:

201 Created
{
  "data": {
    "id": "poll_9aZ2kP",
    "slug": "weekly-retro-jun-16",
    "title": "Weekly retro - week of Jun 16",
    "renderingMode": "LIVE",
    "isPublished": false,
    "accessPin": "6098",
    "shareUrl": "https://pollslive.com/p/weekly-retro-jun-16",
    "createdAt": "2026-06-16T08:00:11.204Z"
  }
}

Passo 2 - Publicar e depois abrir uma sessão ao vivo

Publicar tira um snapshot do conteúdo para que seja seguro apresentá-lo. Um `PATCH /polls/{id}` com `publish: true` faz isso; depois `POST /sessions` cria a sessão do apresentador e devolve o PIN de entrada mais um `hostToken` de uso único (o segredo de autoridade do host - ele só é retornado na criação, então o guardo imediatamente).

PATCH /polls/{id} → POST /sessions
# Publish the draft
curl -sS -X PATCH "$POLLSLIVE_API/polls/poll_9aZ2kP" \
  -H "Authorization: Bearer $POLLSLIVE_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "publish": true }'

# Open a presenter-paced live session
curl -sS -X POST "$POLLSLIVE_API/sessions" \
  -H "Authorization: Bearer $POLLSLIVE_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "pollId": "poll_9aZ2kP", "pace": "PRESENTER" }'
# → { "data": { "id": "ses_4dF1", "pin": "6098",
#       "joinUrl": "https://pollslive.com/join/6098",
#       "hostUrl": "https://pollslive.com/host/ses_4dF1",
#       "hostToken": "hst_…", "status": "LOBBY" } }

Meu cron posta a `joinUrl` e o PIN no canal do time um minuto antes da daily. O pessoal escaneia, e os slides que montei em código são o que eles veem - aqui está o resultado ao vivo do slide `health` depois que todo mundo respondeu:

Live scale
Join at the PIN 6098

Quão saudável esta sprint pareceu? (1 = difícil, 5 = ótima)

5 - Ótima11% · 1
4 - Bem22% · 2
3 - OK22% · 2
2 - Difícil33% · 3
1 - Ruim11% · 1
O slide que defini em JSON, renderizado ao vivo - sem montar deck na mão.

Passo 3 - Puxar resultados e um CSV depois da daily

Quando a sessão termina, `GET /polls/{id}/results` devolve as contagens - `totalVotes`, um mapa `voteCounts` para slides de escolha e um array `slides[]` com agregados por tipo (médias de escala, texto aberto agrupado etc.).

GET /polls/{id}/results
curl -sS "$POLLSLIVE_API/polls/poll_9aZ2kP/results" \
  -H "Authorization: Bearer $POLLSLIVE_KEY"

{
  "data": {
    "pollId": "poll_9aZ2kP",
    "title": "Weekly retro - week of Jun 16",
    "closed": true,
    "totalVotes": 9,
    "voteCounts": { "ci": 4, "tickets": 3, "wip": 2, "meetings": 0 },
    "slides": [
      { "slideId": "health", "kind": "scale", "average": 2.9 },
      { "slideId": "blockers", "kind": "open_ended", "responseCount": 14 },
      { "slideId": "fix", "kind": "multiple_choice",
        "optionCounts": { "ci": 4, "tickets": 3, "wip": 2, "meetings": 0 } }
    ]
  }
}

Para o arquivo, `GET /polls/{id}/export` faz streaming de um CSV no formato RFC-4180 (número do slide, pergunta, tipo, rótulo da resposta, contagem/valor). Eu salvo e anexo à mensagem do Slack. Todo o passo pós-daily é uma pequena função:

summarise.mjs (Node 18+)
const API = process.env.POLLSLIVE_API;
const KEY = process.env.POLLSLIVE_KEY;
const auth = { Authorization: `Bearer ${KEY}` };

export async function summariseRetro(pollId) {
  const res = await fetch(`${API}/polls/${pollId}/results`, { headers: auth });
  if (res.status === 429) throw new Error("rate_limited"); // back off + retry
  if (!res.ok) throw new Error(`results ${res.status}`);
  const { data } = await res.json();

  const winner = Object.entries(data.voteCounts)
    .sort((a, b) => b[1] - a[1])[0];

  // Grab the CSV for the archive
  const csv = await fetch(`${API}/polls/${pollId}/export`, { headers: auth })
    .then((r) => r.text());

  return {
    health: data.slides.find((s) => s.slideId === "health")?.average,
    topFix: winner?.[0],
    voters: data.totalVotes,
    csv,
  };
}

É isso tudo. O deck da retro se monta sozinho, a sessão abre na hora marcada e o resumo + CSV são postados automaticamente. Recuperei meus dez minutos de sexta-feira, e o formato é idêntico toda semana - que é exatamente o que se quer de uma retro.

A parte mais bacana: os slides que descrevo em JSON são os mesmos slides que o time vê e vota. Sem divergência entre 'o que o script fez' e 'o que rodamos'.

A referência completa de endpoints e os schemas estão na referência de API interativa, e o quickstart narrativo está no guia para desenvolvedores. Próximo na minha lista: webhooks, para que o resumo do Slack dispare no instante em que a sessão termina, em vez de num timer - que é exatamente o que o artigo sobre webhooks cobre.

Tip

Use um cron job para clonar o deck de retro da semana passada e publicar um link novo automaticamente.

PollsLive Studio dashboard with poll list, left nav, and Create buttons.
Studio is your home for every poll you have created.
Results panel with stat tiles, breakdown by question, and export buttons.
The Results tab shows every answer and export options.

Alternativa sem código: enquetes recorrentes sem reconstruir.

Desenvolva no PollsLive - crie enquetes, conduza sessões ao vivo, obtenha resultados e receba webhooks pelo seu próprio código.

Leia a documentação para desenvolvedores