Documentação do Zealy

Tradução automática · Ler em inglês

Webhooks

Melhore as capacidades da Zealy com ligações Webhook.

Por louis, Fredrika, benjamin

Webhooks
Nesta página

Um webhook da Zealy envia um HTTP POST para um URL à sua escolha quando um de nove eventos da comunidade ocorre, entre eles a adesão de um membro, o sucesso ou falha de uma claim de quest, o início de um sprint e o banimento de um utilizador. Cada payload inclui um id de evento, tipo, dados, um timestamp em milissegundos e o segredo que prova que o pedido é genuíno.

Noções básicas

A Zealy disponibiliza webhooks que lhe permitem receber notificações push HTTP sempre que os dados são criados ou atualizados. Isto permite-lhe criar integrações por cima da Zealy. Pode acionar builds de CI, efetuar cálculos sobre dados de quests ou enviar mensagens em condições específicas – as possibilidades são infinitas.

Visite Definições > Integrações > Zapier & Webhooks para configurar os seus webhooks.

Como funciona um Webhook?

Um push de Webhook é simplesmente um pedido HTTP POST enviado para o URL à sua escolha. O push é acionado automaticamente pela Linear quando os dados são atualizados. Para um exemplo dos dados contidos num payload, consulte O Payload do Webhook.

O seu consumidor de webhook é um endpoint HTTP simples. Deve cumprir as seguintes condições:

  • Estar disponível num URL HTTPS publicamente acessível, que não seja localhost
  • Responder ao push do Webhook da Zealy (pedido HTTP POST) com uma resposta HTTP 200 ("OK")

Se uma entrega falhar (ou seja, servidor indisponível, resposta demorou mais de 5 segundos, corpo da resposta maior que 5000 bytes ou resposta com um código de estado HTTP diferente de 200), o push será repetido 15 vezes. É utilizado um atraso de backoff exponencial: a tentativa será repetida após aproximadamente 10 minutos, depois 30 minutos, e assim sucessivamente. Se o URL do webhook continuar sem responder, o webhook pode ser desativado pela Zealy e terá de ser reativado manualmente.

Para garantir que um Webhook POST é realmente criado pela Zealy, geramos um segredo aleatório que será anexado ao corpo do pedido no campo secret .

Para informações adicionais sobre Webhooks, existem vários bons recursos:

Para que posso usá-lo?

  • Integrar com o Zapier
  • Automatizar recompensas personalizadas
  • Notificar no Telegram as quests a aguardar revisão

E muito, muito mais!

Começar com os Webhooks da Zealy

  1. Identifique os eventos que pretende monitorizar.
  2. Desenvolva uma função de endpoint de webhook para receber pedidos POST com dados de eventos.
  3. Registe o seu endpoint na Zealy através do Painel de Webhooks em Definições > Integrações > Zapier & Webhooks.
  4. Proteja o seu endpoint de webhook.

Criar um consumidor de Webhook simples

Pode considerar usar algo como Netlify Functions, que oferece uma forma simples de implementar endpoints HTTP(S) simples: https://www.netlify.com/blog/2018/09/13/how-to-run-express.js-apps-with-netlify-functions/.

// server.js
//
// Use this sample code to handle webhook events in your integration.
//
// 1) Paste this code into a new file (server.js)
//
// 2) Install dependencies
//   npm install express
//
// 3) Run the server on http://localhost:4242
//   node server.js
 
// The library needs to be configured with your account's secret key.
// Ensure the key is kept out of any version control system you might be using.
const express = require('express');
const app = express();
 
// This is your Zealy webhook secret for testing your endpoint locally.
const endpointSecret = '5888a6800dbac634e52d8504f097e064';
 
app.post('/webhook', express.raw({ type: 'application/json' }), (request, response) => {
  const payload = req.body;
  // Does createdAt make more sense than time?
  const { id, type, data, time, secret } = payload;
 
  if (secret === endpointSecret) {
    // Do something neat with the data received!
  }
 
  // Return a 200 response to acknowledge receipt of the event
  response.send();
});
 
app.listen(4242, () => console.log('Running on port 4242'));

Configurar nas definições

Configure o webhook e os eventos que deve monitorizar em Definições > Integrações > Webhooks.

O payload do Webhook

O payload HTTP do webhook incluirá informações tanto nos cabeçalhos HTTP como no corpo do pedido.

O payload será enviado com os seguintes cabeçalhos HTTP:

User-Agent: Zealy-Webhook
Content-Type: application/json; charset=utf-8
{
  id: string // unique ID for this event (UUID v4)
  type: "JOINED_COMMUNITY" | "LEFT_COMMUNITY" | "QUEST_SUCCEEDED" | "QUEST_CLAIMED" | "QUEST_FAILED" | "QUEST_CLAIM_STATUS_UPDATED" | "SPRINT_STARTED" | "SPRINT_ENDED" | "USER_BANNED", // event type
  data: EventData, // event data, see below
  time: number, // timestamp, in milliseconds
  secret: string, // secret generated when you created your webhook, used for checking origin
}

Campo EventData por evento:

// JOINED_COMMUNITY
type JoinedCommunityEventData = {
  community: WebhookCommunityPayload;
  user: WebhookUserPayload;
};
 
// LEFT_COMMUNITY
type LeftCommunityEventData = {
  community: WebhookCommunityPayload;
  user: WebhookUserPayload;
};
 
// QUEST_SUCCEEDED
type QuestSucceededEventData = {
  community: WebhookCommunityPayload;
  user: WebhookUserPayload;
  quest: WebhookQuestPayload;
  taskInputs?: Array<{
    taskId: string, // task ID (uuid v4)
    taskType: 'number' | 'date' | 'api' | 'text' | 'discord' | 'url' | 'telegram' | 'quiz' | 'invites' | 'visitLink' | 'file' | 'poll' | 'opinion' | 'twitterFollow' | 'twitterSpace' | 'tweetReact' | 'tweet',
    input: WebhookQuestTaskInputPayload,
  }>;
  status: 'success';
};
 
// QUEST_CLAIMED
type QuestClaimedEventData = {
  community: WebhookCommunityPayload;
  user: WebhookUserPayload;
  quest: WebhookQuestPayload;
  taskInputs?: Array<{
    taskId: string, // task ID (uuid v4)
    taskType: 'number' | 'date' | 'api' | 'text' | 'discord' | 'url' | 'telegram' | 'quiz' | 'invites' | 'visitLink' | 'file' | 'poll' | 'opinion' | 'twitterFollow' | 'twitterSpace' | 'tweetReact' | 'tweet',
    input: WebhookQuestTaskInputPayload,
  }>;
};
 
// QUEST_FAILED
type QuestFailedEventData = {
  community: WebhookCommunityPayload;
  user: WebhookUserPayload;
  quest: WebhookQuestPayload;
  taskInputs?: Array<{
    taskId: string, // task ID (uuid v4)
    taskType: 'number' | 'date' | 'api' | 'text' | 'discord' | 'url' | 'telegram' | 'quiz' | 'invites' | 'visitLink' | 'file' | 'poll' | 'opinion' | 'twitterFollow' | 'twitterSpace' | 'tweetReact' | 'tweet',
    input: WebhookQuestTaskInputPayload,
  }>;
};
 
// QUEST_CLAIM_STATUS_UPDATED
type QuestClaimStatusUpdatedEventData = {
  community: WebhookCommunityPayload;
  user: WebhookUserPayload;
  quest: WebhookQuestPayload;
  taskInputs?: Array<{
    taskId: string, // task ID (uuid v4)
    taskType: 'number' | 'date' | 'api' | 'text' | 'discord' | 'url' | 'telegram' | 'quiz' | 'invites' | 'visitLink' | 'file' | 'poll' | 'opinion' | 'twitterFollow' | 'twitterSpace' | 'tweetReact' | 'tweet',
    input: WebhookQuestTaskInputPayload,
  }>;
  status: 'success' | 'pending' | 'failed';
};
 
// SPRINT_STARTED
type SprintStartedEventData = {
  community: WebhookCommunityPayload;
  sprint: WebhookSprintPayload;
};
 
// SPRINT_ENDED
type SprintEndedEventData = {
  community: WebhookCommunityPayload;
  sprint: WebhookSprintPayload;
};
 
// USER_BANNED
type UserBannedEventData = {
  community: WebhookCommunityPayload;
  user: WebhookUserPayload;
};

Entidades comuns:

type WebhookCommunityPayload = {
  id: string; // community ID (uuid V4)
  name: string; // community name
  subdomain: string; // community subdomain
  blockchain: string;
  discord: string | null; // discord URI of the community, e.g., https://discord.gg/zealy
  twitter: string | null; // twitter handle of the community, e.g., zealy_io
  website: string | null; // website URI of the community
};
type WebhookUserPayload = {
  id: string; // user ID (uuid V4)
  name: string | null; // user display name
  twitter: {
    id: string; // user twitter ID
    username: string | null; // user twitter handle
  } | null;
  discord: {
    id: string; // user discord ID
    handle: string | null; // user discord handle
  } | null;
  email: string | null; // user email
  addresses: Dict<string>; // key/value dictionary for wallets
  verifiedAddresses: Dict<string>; // key/value dictionary for all users verified wallets
};
type WebhookQuestPayload = {
  id: string; // quest ID (uuid V4)
  name: string; // quest display name
  categoryId: string; // category ID (uuid V4)
  categoryName: string | null; // category display name
  xp: number | null; // XP reward
  published: boolean | null; // true if quest is published, false otherwise
  autoValidate: boolean | null;
  tasks: TaskPayload[];
  lastReviewerId: string; // user ID (uuid V4)
};
type WebhookQuestTaskInputPayload =
 | { } // for task type 'visitLink', 'invites', 'discord', 'telegram', 'twitterFollow', 'twitterSpace'
 | { value: string } // for task type 'text', 'date', 'url', 'opinion'
 | { value: number } // for task type 'number'
 | { values: string[] } // for task type 'poll', 'quiz'
 | { fileUrls: string[] } // for task type 'fileUrls'
 | { tweetId?: string } // for task type 'tweetReact', 'tweet'
 | { requestId: string, statusCode: number } // for task type 'api'
type WebhookSprintPayload = {
  id: string; // sprint ID (uuid V4)
  startingAt: ISOString; // sprint starting date - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
  endingAt: ISOString; // sprint ending date
};

Proteger webhooks

Criar um webhook gera um segredo aleatório que pode usar para verificar que o pedido vem dos webhooks da Zealy. Copie o segredo no canto superior direito do painel de inspeção do webhook e verifique se o segredo definido no corpo do pedido POST é o mesmo.

Caso o segredo seja divulgado, pode regenerá-lo a partir da mesma página.

O painel de inspeção do webhook com o botão Copiar segredo e um menu aberto com Editar webhook, Desativar, Acionar evento de teste, Regenerar segredo e Eliminar webhook

Testar webhooks

A partir do painel de inspeção do webhook pode acionar manualmente um evento de teste. Clique no botão no canto superior direito e selecione ‘Enviar evento de teste’. Poderá selecionar um tipo de evento entre os tipos de eventos monitorizados. Será acionado um evento com dados simulados e o estado será apresentado.

Depuração

Pode ver os registos de todos os eventos passados acionados pelo webhook se clicar no webhook na página Webhooks. Filtrando pelo estado, pode usar os registos para depurar se algo correu mal. Para cada evento, pode ver a mensagem de erro recebida e o pedido que foi enviado.

Também pode repetir qualquer evento a partir desta página.

O registo de eventos do webhook a listar eventos Join community, com as tentativas de entrega de um evento, o payload do pedido e a resposta de erro apresentados

FAQ