Webhooks
Rozszerz możliwości Zealy dzięki połączeniom webhook.
Autor: louis, Fredrika, benjamin

Na tej stronie
Webhook Zealy wysyła żądanie HTTP POST na wybrany przez Ciebie URL, gdy wystąpi jedno z dziewięciu zdarzeń społeczności, m.in. dołączenie członka, powodzenie lub niepowodzenie zgłoszenia questa, rozpoczęcie sprintu oraz zbanowanie użytkownika. Każdy payload zawiera identyfikator zdarzenia, typ, dane, znacznik czasu w milisekundach oraz sekret potwierdzający autentyczność żądania.
Podstawy
Zealy udostępnia webhooki , które pozwalają otrzymywać powiadomienia push HTTP za każdym razem, gdy dane są tworzone lub aktualizowane. Dzięki temu możesz budować integracje na bazie Zealy. Możesz wyzwalać kompilacje CI, wykonywać obliczenia na danych questów lub wysyłać wiadomości w określonych warunkach – możliwości są nieograniczone.
Przejdź do Settings > Integrations > Zapier & Webhooks, aby skonfigurować webhooki.
Jak działa Webhook?
Push Webhooka to po prostu HTTP POST żądanie wysłane na wybrany przez Ciebie URL. Push jest automatycznie wyzwalany przez Linear, gdy dane zostaną zaktualizowane. Przykład danych zawartych w payloadzie znajdziesz w Payload Webhooka.
Twój konsument webhooka to prosty endpoint HTTP. Musi spełniać następujące warunki:
- Jest dostępny pod publicznie dostępnym adresem URL HTTPS, niebędącym localhost
- Odpowie na push Webhooka Zealy (żądanie HTTP POST) odpowiedzią
HTTP 200("OK")
Jeśli dostarczenie się nie powiedzie (np. serwer niedostępny, odpowiedź trwała dłużej niż 5 sekund, treść odpowiedzi była większa niż 5000 bajtów lub odpowiedź miała kod statusu HTTP inny niż 200), wysyłka zostanie ponowiona 15 razy. Stosowane jest wykładnicze opóźnienie: próba zostanie ponowiona po około 10 minutach, następnie po 30 minutach itd. Jeśli adres URL webhooka nadal nie odpowiada, webhook może zostać wyłączony przez Zealy i trzeba będzie włączyć go ponownie ręcznie.
Aby upewnić się, że webhook POST jest rzeczywiście utworzony przez Zealy, generujemy losowy sekret, który zostanie dołączony do treści żądania w polu secret .
Dodatkowe informacje o webhookach można znaleźć w kilku dobrych źródłach:
- RequestBin: Webhooks – The Definitive Guide
- requestbin.com to świetne narzędzie do testowania webhooków
- Przewodnik dla deweloperów GitHub: Webhooks
Do czego mogę to wykorzystać?
- Integracja z Zapier
- Automatyzacja niestandardowych nagród
- Powiadamiaj o questach oczekujących na weryfikację na Telegramie
I wiele, wiele więcej!
Pierwsze kroki z Zealy Webhooks
- Określ, które zdarzenia chcesz monitorować.
- Opracuj funkcję endpointu webhooka do odbierania żądań POST z danymi zdarzeń.
- Zarejestruj swój endpoint w Zealy za pomocą panelu Webhooks w Ustawienia > Integracje > Zapier i Webhooks.
- Zabezpiecz swój endpoint webhooka.
Tworzenie prostego konsumenta Webhooka
Możesz rozważyć użycie czegoś takiego jak Netlify Functions, które zapewnia prosty sposób wdrażania prostych endpointów HTTP(S): 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'));Konfigurowanie w ustawieniach
Skonfiguruj webhook i zdarzenia, które ma monitorować, w Ustawienia > Integracje > Webhooks.
Ładunek webhooka
Ładunek HTTP webhooka będzie zawierać informacje zarówno w nagłówkach HTTP, jak i w treści żądania.
Ładunek zostanie wysłany z następującymi nagłówkami 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
}Pole EventData dla każdego zdarzenia:
// 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;
};Wspólne encje:
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
};Zabezpieczanie webhooków
Utworzenie webhooka wygeneruje losowy sekret, którego możesz użyć do weryfikacji, że żądanie pochodzi z webhooków Zealy. Skopiuj sekret w prawym górnym rogu panelu inspekcji webhooka i sprawdź, czy sekret ustawiony w treści żądania POST jest taki sam.
W przypadku wycieku sekretu możesz go wygenerować ponownie z tej samej strony.

Testowanie webhooków
W panelu inspekcji webhooka możesz ręcznie wyzwolić zdarzenie testowe. Kliknij przycisk w prawym górnym rogu i wybierz „Wyślij zdarzenie testowe”. Będziesz mógł wybrać typ zdarzenia spośród monitorowanych typów zdarzeń. Zdarzenie zostanie wyzwolone z danymi testowymi, a status zostanie wyświetlony.
Debugowanie
Możesz zobaczyć logi wszystkich przeszłych zdarzeń wyzwolonych przez webhook, jeśli klikniesz webhook na stronie Webhooki. Filtrując według statusu, możesz użyć logów do debugowania, jeśli coś poszło nie tak. Dla każdego zdarzenia możesz zobaczyć otrzymany komunikat o błędzie i wysłane żądanie.
Możesz także ponowić dowolne zdarzenie z tej strony.
