Zealy-documentatie

Automatisch vertaald · Lees in het Engels

Webhooks

Vergroot de mogelijkheden van Zealy met webhookverbindingen.

Door louis, Fredrika, benjamin

Webhooks
Op deze pagina

Een Zealy-webhook stuurt een HTTP POST naar een URL die je kiest wanneer een van de negen community-evenementen plaatsvindt, waaronder een lid dat lid wordt, een quest-claim die slaagt of mislukt, een sprint die start en een gebruiker die wordt verbannen. Elke payload bevat een event-id, type, data, een tijdstempel in milliseconden en het geheim dat bewijst dat het verzoek echt is.

Basis

Zealy biedt webhooks waarmee je HTTP-pushmeldingen kunt ontvangen wanneer gegevens worden aangemaakt of bijgewerkt. Zo kun je integraties bovenop Zealy bouwen. Je kunt CI-builds triggeren, berekeningen uitvoeren op questgegevens of berichten versturen onder specifieke voorwaarden – noem maar op.

Ga naar Instellingen > Integraties > Zapier & Webhooks om je webhooks in te stellen.

Hoe werkt een Webhook?

Een Webhook-push is simpelweg een HTTP POST verzoek, verzonden naar de URL van je keuze. De push wordt automatisch geactiveerd door Linear wanneer gegevens worden bijgewerkt. Voor een voorbeeld van welke gegevens een payload bevat, zie De Webhook-payload.

Je webhook-consumer is een eenvoudig HTTP-endpoint. Het moet aan de volgende voorwaarden voldoen:

  • Het is beschikbaar op een openbaar toegankelijke HTTPS-URL die niet localhost is
  • Het reageert op de Zealy Webhook-push (HTTP POST-verzoek) met een HTTP 200 ("OK")-reactie

Als een levering mislukt (bijv. server niet beschikbaar, reactie duurde langer dan 5 seconden, de response body was groter dan 5000 bytes of er werd gereageerd met een andere HTTP-statuscode dan 200), wordt de push 15 keer opnieuw geprobeerd. Hierbij wordt een exponentiële backoff-vertraging gebruikt: de poging wordt opnieuw geprobeerd na ongeveer 10 minuten, daarna 30 minuten, enzovoort. Als de webhook-URL onbereikbaar blijft, kan de webhook door Zealy worden uitgeschakeld en moet deze handmatig opnieuw worden ingeschakeld.

Om ervoor te zorgen dat een webhook POST echt door Zealy is aangemaakt, genereren we een geheim dat willekeurig is en wordt toegevoegd aan de body van het verzoek in het secret veld.

Voor meer informatie over webhooks zijn er verschillende goede bronnen:

Waarvoor kan ik het gebruiken?

  • Integreren met Zapier
  • Aangepaste beloningen automatiseren
  • Quests die op beoordeling wachten melden op Telegram

En nog veel meer!

Aan de slag met Zealy Webhooks

  1. Bepaal welke gebeurtenissen je wilt volgen.
  2. Ontwikkel een webhook-endpointfunctie om POST-verzoeken met gebeurtenisgegevens te ontvangen.
  3. Registreer je endpoint binnen Zealy via het Webhooks-dashboard in Instellingen > Integraties > Zapier & Webhooks.
  4. Beveilig je webhook-endpoint.

Een eenvoudige webhook-consumer maken

Je kunt overwegen iets als Netlify Functions te gebruiken, dat een eenvoudige manier biedt om simpele HTTP(S)-endpoints te deployen: 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'));

Configureren in instellingen

Stel de webhook en de gebeurtenissen die deze moet monitoren in via Instellingen > Integraties > Webhooks.

De Webhook-payload

De HTTP-payload van de webhook bevat informatie in zowel de HTTP-headers als de request body.

De payload wordt verzonden met de volgende HTTP-headers:

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
}

EventData-veld per event:

// 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;
};

Gemeenschappelijke entiteiten:

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
};

Webhooks beveiligen

Bij het aanmaken van een webhook wordt een willekeurig geheim aangemaakt dat je kunt gebruiken om te verifiëren dat het verzoek afkomstig is van Zealy-webhooks. Kopieer het geheim rechtsboven in het inspectiepaneel van de webhook en controleer of het geheim in de body van het POST-verzoek hetzelfde is.

Als het geheim uitlekt, kun je het opnieuw genereren op dezelfde pagina.

Het webhook-inspectiepaneel met de knop Copy secret en een open menu met Edit webhook, Disable, Trigger test event, Regenerate secret en Delete webhook

Webhooks testen

Vanuit het inspectiepaneel van de webhook kun je handmatig een testgebeurtenis activeren. Klik op de knop rechtsboven en selecteer ‘Send test event’. Je kunt een gebeurtenistype kiezen uit de gemonitorde gebeurtenistypen. Er wordt een gebeurtenis geactiveerd met mockdata en de status wordt weergegeven.

Debuggen

Je kunt de logs van alle eerdere gebeurtenissen die door de webhook zijn geactiveerd bekijken door op de webhook te klikken op de pagina Webhooks. Door op status te filteren kun je de logs gebruiken om te debuggen als er iets mis is gegaan. Voor elke gebeurtenis kun je het ontvangen foutbericht en het verzonden verzoek zien.

Je kunt ook elke gebeurtenis vanaf deze pagina opnieuw proberen.

De gebeurtenislog van de webhook met Join community-gebeurtenissen, waarbij van één gebeurtenis de leveringspogingen, de request-payload en de foutrespons worden getoond

FAQ