Pular para o conteúdo principal

Evento: Resposta de formulário registrada (FORM_RESPONSE_ADDED)

Dispara quando uma resposta de formulário de um candidato é registrada — por exemplo, um questionário de triagem ou um formulário personalizado.

Novo nos webhooks? Veja a visão geral para o conceito (registrar uma vez, receber sempre que a ação ocorre).

Criando o webhook​

Registre um webhook para o evento FORM_RESPONSE_ADDED (Criar webhook):

curl -X POST https://api.inhire.app/integrations/webhooks \
-H "Authorization: Bearer SEU_ACCESS_TOKEN" \
-H "X-Tenant: suaempresa" \
-H "Content-Type: application/json" \
-d '{
"name": "Resposta de formulário",
"event": "FORM_RESPONSE_ADDED",
"url": "https://seu-sistema.com/webhooks/inhire/formulario",
"headers": { "Authorization": "Bearer UM_SEGREDO_SEU" }
}'

A partir daí, o InHire chamará a sua URL sempre que este evento ocorrer. Para filtrar quais ocorrências recebe, adicione rules (ver abaixo).

Payload​

{
"tenantId": "suaempresa",
"jobId": "5dfd3a1e-a5c3-4e53-a3f4-cdb4e311d315",
"talentId": "b1c2d3e4-f5a6-7890-bcde-1234567890ab",
"type": "subscription",
"title": "Triagem técnica",
"vendor": "typeform",
"typeformId": "abc123",
"formResponseId": "abc123",
"passed": true,
"correctQuestionsCount": 8,
"autoCorrectionResult": {},
"answers": [
{
"question": {
"id": "Q1abc",
"ref": "anos-experiencia",
"type": "short_text",
"title": "Quantos anos de experiência você tem?"
},
"answer": {
"field": { "id": "Q1abc", "type": "short_text" },
"type": "text",
"text": "5 anos"
}
},
{
"question": {
"id": "Q2def",
"ref": "conhece-sql",
"type": "multiple_choice",
"title": "Você conhece SQL?"
},
"answer": {
"field": { "id": "Q2def", "type": "multiple_choice" },
"type": "choices",
"choices": [
{ "ref": "c1", "label": "Sim", "selected": true, "weight": 10, "correct": true },
{ "ref": "c2", "label": "Não", "selected": false, "weight": 0, "correct": false }
]
}
}
]
}
CampoDescrição
jobId / talentIdVaga e talento associados à resposta
typeTipo do formulário
titleTítulo do formulário
passedIndica se o candidato foi aprovado na correção automática
correctQuestionsCountNúmero de questões corretas
answersPerguntas e respostas já relacionadas — cada item tem question e answer (ver abaixo)
autoCorrectionResultDetalhe da correção automática, quando aplicável
informação

As perguntas e as respostas já vêm no payload, dentro de answers. Cada item tem:

  • question: a pergunta (id, ref, type, title e, em questões de múltipla escolha, properties.choices).
  • answer: a resposta. O formato depende do type:
    • texto/número/etc.: campo direto, ex.: answer.text, answer.number, answer.email.
    • múltipla escolha (type: "choices"): array answer.choices com label, selected, weight e correct por alternativa.

Itens sem answer significam perguntas que o candidato não respondeu. Você não precisa chamar a API para obter as perguntas — elas já estão aqui.

Quando usar​

  • Avançar ou reprovar automaticamente um candidato com base no resultado (passed).
  • Registrar a nota do questionário em um sistema externo.
  • Notificar o recrutador quando um candidato passa de um corte mínimo.

Filtrando com rules​

// Apenas respostas aprovadas
{ "passed": { "operator": "=", "value": true } }

Exemplo: lendo as respostas e buscando o candidato​

As perguntas e respostas já vêm no payload em answers — basta iterar. O jobId e o talentId permitem buscar os dados completos do talento e da candidatura na API:

import express from "express";
import axios from "axios";

const app = express();
app.use(express.json());

// Cliente autenticado da API do InHire (use um service account — ver guia de Autenticação)
const inhire = axios.create({
baseURL: "https://api.inhire.app",
headers: {
Authorization: `Bearer ${process.env.INHIRE_TOKEN}`,
"X-Tenant": "suaempresa",
},
});

// Extrai o valor de uma resposta conforme o tipo
function valorDaResposta(answer) {
if (!answer) return null; // pergunta não respondida
if (answer.type === "choices") {
return answer.choices.filter(c => c.selected).map(c => c.label);
}
return answer.text ?? answer.number ?? answer.email ?? answer.boolean ?? answer.date;
}

app.post("/webhooks/inhire/formulario", async (req, res) => {
// Valide a origem usando o header secreto configurado no webhook
if (req.headers.authorization !== "Bearer UM_SEGREDO_SEU") {
return res.sendStatus(401);
}
res.sendStatus(200); // responda rápido e processe de forma assíncrona

const { jobId, talentId, title, passed, answers } = req.body;

// 1. Lê as perguntas e respostas direto do payload
for (const item of answers) {
console.log(`${item.question.title}: ${JSON.stringify(valorDaResposta(item.answer))}`);
}

// 2. Busca os dados completos do talento e da candidatura
const [{ data: talento }, { data: candidatura }] = await Promise.all([
inhire.get(`/talents/${talentId}`), // o talento
inhire.get(`/job-talents/${jobId}/talents/${talentId}`), // o talento na vaga (candidatura)
]);

console.log(`${talento.name} ${passed ? "passou" : "não passou"} no formulário "${title}"`);

// ...sua lógica aqui (ex.: avançar/reprovar a candidatura)
});

app.listen(3000);

Endpoints usados: Obter talento e Obter candidaturas de um talento.