# Formulário de inscrição de voluntários com turnos, para eventos e festivais

> Um formulário de inscrição de voluntários em que as pessoas escolhem turnos, com telefone para o dia, e um script que mostra os turnos desfalcados e monta a escala.

Publicado em 2026-10-25 · https://ikiform.com/pt-br/guides/event-registration/volunteer-signup

Deixe os voluntários marcarem num único formulário todos os turnos que podem fazer, com telefone, tamanho de camiseta e um contato de emergência, e envie ao Ikiform. O Ikiform armazena cada inscrição e avisa os coordenadores por e-mail, mas não preenche nem fecha turnos, então rode um script curto que conta os voluntários por turno em relação ao que você precisa e monta uma escala. Complete os turnos desfalcados chamando diretamente os voluntários que sobraram.

## O que muda com voluntários

Um RSVP faz uma pergunta: você vem? Uma inscrição de voluntário pergunta quando, e a resposta só importa diante do que cada turno precisa. A montagem às 7h precisa de seis pessoas e recebe duas; a tarde de sol precisa de dez e recebe dezenove. O trabalho não é contar pessoas, é cobrir os turnos.

- **Disponibilidade, não uma escolha única.** As pessoas podem fazer vários turnos. Peça todos os turnos que elas poderiam fazer e distribua a partir disso, em vez de fazê-las adivinhar o que falta.
- **Contato no dia.** O e-mail serve para o planejamento. No dia você precisa de um celular e de um contato de emergência para cada voluntário.
- **Coisas para encomendar.** Camisetas, crachás com cordão e almoços, por tamanho e quantidade.
- **Idade.** Muitos eventos exigem que cada voluntário seja maior de idade ou tenha a concordância de um responsável. Pergunte à sua organização o que se aplica; um checkbox registra a resposta, mas não é uma verificação legal.

Plataformas de voluntariado como o SignUpGenius fazem inscrições por vaga e fecham uma vaga quando ela lota. Se limites rígidos por vaga são o que você precisa, use uma delas. O Ikiform serve para organizadores que querem o formulário no próprio site e não se importam de distribuir os turnos à mão a partir de uma lista limpa.

Diagrama: Transformando a disponibilidade dos voluntários numa escala que mostra as lacunas

1. Os voluntários marcam no formulário de inscrição todos os turnos que poderiam fazer, e ele envia ao Ikiform.
2. O Ikiform armazena cada inscrição e avisa os coordenadores por e-mail.
3. Um script lê as inscrições pela API e conta os voluntários por turno em relação ao que cada turno precisa.
4. Ele grava o rota.csv com nomes e telefones para cada turno.
5. Os turnos desfalcados aparecem na hora, como a montagem com 2 de 6, para você chamar voluntários que estão sobrando em outros turnos.

O Ikiform guarda a disponibilidade. O script a transforma em cobertura, e um coordenador toma as decisões finais.

## O formulário

Agrupe os turnos por dia para as pessoas conseguirem passar o olho. Os checkboxes se chamam `shifts[]`, então até uma única marcação é armazenada como lista. Funciona como HTML puro em qualquer site ou criador de sites que aceite um embed:

`volunteer.html`:

```html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <label>Name <input name="name" autocomplete="name" required></label>
  <label>Email <input name="email" type="email" autocomplete="email" required></label>
  <label>Mobile number for the day <input name="phone" type="tel" autocomplete="tel" placeholder="+44 7700 900123" required></label>

  <fieldset>
    <legend>Shifts you can do</legend>
    <p>Saturday</p>
    <label><input type="checkbox" name="shifts[]" value="sat_setup"> 7:00 to 10:00, setup</label>
    <label><input type="checkbox" name="shifts[]" value="sat_day"> 10:00 to 14:00</label>
    <label><input type="checkbox" name="shifts[]" value="sat_late"> 14:00 to 18:00</label>
    <p>Sunday</p>
    <label><input type="checkbox" name="shifts[]" value="sun_day"> 10:00 to 14:00</label>
    <label><input type="checkbox" name="shifts[]" value="sun_pack"> 14:00 to 17:00, pack-down</label>
  </fieldset>

  <label>Where you'd like to help
    <select name="role">
      <option value="anywhere">Anywhere</option>
      <option value="welcome">Welcome desk</option>
      <option value="food">Food stall</option>
      <option value="stewarding">Stewarding</option>
    </select>
  </label>
  <label>T-shirt size
    <select name="tshirt" required>
      <option value="s">S</option><option value="m" selected>M</option><option value="l">L</option>
      <option value="xl">XL</option><option value="xxl">XXL</option>
    </select>
  </label>
  <label>Emergency contact name and number <input name="emergency_contact" required maxlength="160"></label>
  <label><input type="checkbox" name="adult" required> I'm 18 or over, or a parent or guardian is filling this in with me</label>

  <input type="hidden" name="_redirect" value="https://fair.example/volunteers/thanks">
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden>
  <button type="submit">Sign me up</button>
</form>
```

Cole esta definição na aba **Fields** do formulário. O servidor então recusa uma inscrição sem turnos, com um telefone que não é telefone ou com o checkbox de idade desmarcado, venha de qual página vier:

Formulário: Volunteer signup

- **Nome** (`name`, text, obrigatório)
- **E-mail** (`email`, email, obrigatório)
- **Celular para o dia** (`phone`, phone, obrigatório)
- **Turnos que você pode fazer** (`shifts`, multi_select, obrigatório)
- **Onde você gostaria de ajudar** (`role`, select)
- **Tamanho da camiseta** (`tshirt`, select, obrigatório)
- **Nome e telefone do contato de emergência** (`emergency_contact`, text, obrigatório)
- **Tenho 18 anos ou mais, ou um pai, mãe ou responsável está preenchendo isto comigo** (`adult`, checkbox, obrigatório)

`shifts` é um `multi_select` com `min_items: 1`. `phone` é um campo `phone`, que confere o formato do número. `adult` precisa estar marcado.

| Campo | Por que está aqui |
| --- | --- |
| `phone` | Avisar mudanças de turno por SMS e encontrar as pessoas no dia |
| `shifts` | A disponibilidade a partir da qual você distribui |
| `role` | Preferências, para a recepção ficar com quem pediu por ela |
| `tshirt` | O pedido que você faz duas semanas antes |
| `emergency_contact` | Para a equipe de primeiros socorros, não para marketing |
| `adult` | A regra de idade da sua organização, registrada num envio que guarda o seu próprio `created_at` |

> Telefones e contatos de emergência são dados pessoais de pessoas que não estão se inscrevendo elas mesmas. Guarde a exportação num lugar privado, compartilhe a escala só com os líderes de turno e exclua os envios depois do evento.

## Monte a escala e veja as lacunas

Rode isto com Node e uma chave de API secreta sempre que quiser ver o panorama. Ele pega a inscrição mais nova de cada voluntário, mostra cada turno como completo, desfalcado ou com sobra, e grava `rota.csv` com nomes e telefones de cada turno:

`rota.ts`:

```ts
import { writeFileSync } from "node:fs";
import { createClient } from "@ikiform/sdk";

const NEEDED: Record<string, number> = { sat_setup: 6, sat_day: 10, sat_late: 10, sun_day: 8, sun_pack: 6 };
const ikiform = createClient({ apiKey: process.env.IKIFORM_SECRET_KEY! });
const people = new Map<string, Record<string, unknown>>();

for await (const submission of ikiform.submissions.iterate({ formId: "frm_xxxxxxxxxxxxxxxx", status: "received", limit: 100 })) {
  const email = String(submission.fields.email ?? "").trim().toLowerCase();
  if (email && !people.has(email)) people.set(email, submission.fields);
}

const cell = (value: unknown) => `"${String(value ?? "").replaceAll('"', '""')}"`;
const rows = [["shift", "name", "phone", "role", "tshirt"].join(",")];

for (const [shift, needed] of Object.entries(NEEDED)) {
  const team = [...people.values()].filter((fields) => (fields.shifts as string[] | undefined)?.includes(shift));
  const state = team.length < needed ? `SHORT ${needed - team.length}` : team.length > needed ? "spare" : "ok";
  console.log(`${shift.padEnd(10)} ${team.length}/${needed} ${state}`);
  for (const fields of team) {
    rows.push([shift, fields.name, fields.phone, fields.role, fields.tshirt].map(cell).join(","));
  }
}

writeFileSync("rota.csv", `${rows.join("\n")}\n`);
```

- As listas vêm da mais nova para a mais antiga, então um voluntário que se inscreve de novo com outra disponibilidade é contado pela resposta mais recente.
- Uma pessoa aparece em todos os turnos que marcou. Isso é disponibilidade. Reduza isso a atribuições no CSV e informe a cada pessoa os turnos finais dela.
- Vírgulas e aspas nos nomes são escapadas, então o CSV abre sem problemas em qualquer planilha.

Para uma olhada rápida sem código, exporte o CSV em **Submissions** e filtre a coluna `shifts` pelo valor de um turno, como `sat_setup`. Na exportação, os valores de seleção múltipla ficam juntos numa única célula.

## Da disponibilidade às atribuições

1. Duas semanas antes, rode a escala e encomende as camisetas a partir das contagens de `tshirt`.
2. Para cada turno desfalcado, mande mensagem aos voluntários que estão sobrando e também marcaram aquele turno. Eles já disseram que podiam.
3. Envie a cada voluntário os turnos finais dele pela sua ferramenta de e-mail ou de mensagens. O **Reply** do e-mail de notificação vai direto para ele.
4. Na véspera, imprima a escala para os líderes de turno, com os telefones.

O Ikiform não envia e-mail para quem preenche o formulário. Os e-mails de notificação vão só para você e sua equipe, então não há resposta automática, e-mail de confirmação nem double opt-in. Envie esses e-mails pela sua ferramenta de e-mail, disparados por um [webhook](https://ikiform.com/pt-br/docs/webhooks.md). Os voluntários esquecem para o que se inscreveram, então envie a escala final pessoalmente uma semana antes e de novo na noite anterior.

Para saber de cada inscrição onde sua equipe já conversa, envie o webhook para o [Slack](https://ikiform.com/blog/form-submissions-to-slack.md) ou o [Discord](https://ikiform.com/blog/form-submissions-to-discord.md). Assim os coordenadores veem um turno desfalcado se completar em tempo real.

## Confira antes de recrutar

1. Em **Allowed domains** do formulário, adicione o domínio do seu site, mais `localhost` enquanto desenvolve. Deixe vazio para aceitar envios de qualquer lugar.
2. Inscreva-se com um turno marcado. No painel, `shifts` é uma lista com um valor.
3. Tente se inscrever sem turnos, ou com o checkbox de idade desmarcado. O navegador impede, e um envio forjado recebe `422`.
4. Confira a caixa de entrada de cada destinatário das notificações. Cada um recebe um e-mail com os campos, e **Reply** vai para quem enviou quando o formulário tem um campo `email`.
5. Rode o script da escala. Seu teste aparece no turno dele, e todos os outros turnos aparecem como desfalcados.
6. Abra o `rota.csv` numa planilha e confira a coluna de telefone.

## Pegadinhas

| Problema | O que fazer |
| --- | --- |
| Um único turno é armazenado como texto, não como lista | Os checkboxes se chamam `shifts` sem `[]`, e nenhum campo está definido. Renomeie para `shifts[]`, ou defina `shifts` como `multi_select`. |
| `422` em `phone` | O número não parece um telefone. Peça o código do país no texto de ajuda, como a definição faz. |
| Um voluntário aparece duas vezes na escala | Ele se inscreveu com dois e-mails diferentes. Junte os dois à mão; o script usa o e-mail como chave. |
| `422 validation_failed` | O envio não corresponde à definição de campos do formulário. `error.fields` aponta cada campo e o motivo. Faça o `name` do input bater com o id do campo. |
| `429 rate_limited` | Um visitante enviou mais do que o limite de taxa do formulário permite. O Standard permite 5 por minuto por visitante. Espere o `Retry-After`, ou escolha Relaxed ou Custom para formulários que enviam a partir de um único IP compartilhado. |

## Perguntas

### O Ikiform consegue fechar um turno quando ele lota?

Não. O Ikiform não tem limites por opção. Peça a disponibilidade, conte os voluntários por turno com um script ou uma planilha e distribua as pessoas você mesmo. Use uma ferramenta de inscrição por vagas se limites rígidos importarem mais.

### Como recebo vários turnos de um mesmo voluntário?

Use checkboxes chamados shifts[] e defina shifts como um campo multi_select. Todo turno marcado é armazenado numa única lista, e min_items: 1 torna pelo menos um obrigatório.

### Os voluntários podem mudar de turno?

Peça para se inscreverem de novo com o mesmo e-mail. O script da escala usa a inscrição mais nova de cada voluntário, então a nova disponibilidade substitui a antiga.

### O Ikiform pode enviar e-mail para quem preencheu o formulário?

Não. O Ikiform envia e-mail para você e sua equipe, não para quem enviou, então não há resposta automática nem e-mail de confirmação. Envie um webhook para sua ferramenta de e-mail e mande a confirmação de lá.

### O Ikiform é gratuito?

Não, não há plano gratuito. Testar é grátis: você pode enviar 50 envios de teste por mês a partir de localhost antes de pagar. Para entrar no ar, o Pro começa em US$ 6/mês para 500 envios, ou você pode pagar uma vez 10.000 envios por US$ 49 ou 50.000 envios por US$ 149, com créditos que nunca expiram.

## Mais guias

- [Inscrição em eventos](https://ikiform.com/pt-br/guides/event-registration.md): Receba confirmações de presença na página do seu evento: formulário, limite de convidados, contagem honesta, encerramento ao lotar e lista de check-in, sem app de ingressos.
- [Sem Eventbrite](https://ikiform.com/pt-br/guides/event-registration/without-eventbrite.md): Faça as inscrições de um evento comunitário gratuito no seu próprio site: escolha de sessões, e-mail de confirmação pela sua ferramenta, contagem por sala e lista de check-in.
- [RSVP de casamento](https://ikiform.com/pt-br/guides/event-registration/wedding-rsvp.md): Um formulário de RSVP para um site de casamento feito por você: uma resposta por convite, uma refeição por convidado, um prazo e a lista de quem não respondeu.
