Skip to content

Commit 2189982

Browse files
author
Mohamed Elghobaty
committed
update typescript docs
1 parent 83a8815 commit 2189982

File tree

1 file changed

+52
-16
lines changed

1 file changed

+52
-16
lines changed

api-reference/webhooks/typescript.mdx

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,70 @@ title: 'Webhooks and Typescript'
33
sidebarTitle: 'Using Typescript'
44
---
55

6-
When using webhooks with Typescript, you can use a utility called `parsePlainWebhook` in the Typescript SDK to parse the webhook requests.
6+
Our [TypeScript SDK](https://github.com/team-plain/typescript-sdk) provide utilities to [verify the webhook signature](https://www.plain.com/docs/api-reference/request-signing#request-signing) and parse the webhook body into a typed object.
77

8-
This makes sure your code is 100% type safe and that all requests are correctly validated.
8+
```typescript
9+
import express from 'express';
910

10-
```ts
11-
import Express from 'express';
12-
import { parsePlainWebhook } from '@team-plain/typescript-sdk';
11+
import {
12+
PlainWebhookSignatureVerificationError,
13+
PlainWebhookVersionMismatchError,
14+
verifyPlainWebhook,
15+
} from '@team-plain/typescript-sdk';
1316

14-
const app = Express();
17+
// Plain HMAC Secret. You can find this in Plain's settings.
18+
const PLAIN_SIGNATURE_SECRET = process.env.PLAIN_SIGNATURE_SECRET;
19+
if (!PLAIN_SIGNATURE_SECRET) {
20+
throw new Error('PLAIN_SIGNATURE_SECRET environment variable is required');
21+
}
1522

16-
app.post('/handler/', function (req: Express.Request, res: Express.Response) {
17-
const parseResult = parsePlainWebhook(req.body);
23+
const app = express();
24+
app.use(express.text());
1825

19-
// If this errors it means the request is not valid
20-
// you can safely ignore it!
21-
if (parseResult.error) {
22-
res.status(400);
26+
app.post('/handler', function (req: Express.Request, res: Express.Response) {
27+
// Please note that you must pass the raw request body, exactly as received from Plain,
28+
const payload = req.body;
29+
30+
// Plain's computed signature for the request.
31+
const signature = req.get('Plain-Request-Signature');
32+
33+
const webhookResult = verifyPlainWebhook(payload, signature, secret);
34+
if (webhookResult.error instanceof PlainWebhookSignatureVerificationError) {
35+
res.status(401).send('Failed to verify the webhook signature');
36+
return;
37+
}
38+
39+
if (webhookResult.error instanceof PlainWebhookVersionMismatchError) {
40+
// The SDK is not compatible with the received webhook version.
41+
// This can happen if you upgrade the SDK but not the webhook target, or vice versa.
42+
// We recommend setting up alerts to notify you when this happens.
43+
// Consult https://plain.com/docs/api-reference/webhooks/versions for more information.
44+
console.error('Webhook version mismatch:', webhookResult.error.message);
45+
46+
// Respond with a non-2XX status code to trigger a retry from Plain.
47+
res.status(400).send('Webhook version mismatch');
2348
return;
2449
}
2550

26-
// This is now fully typed and safe to use.
27-
const webhookBody = parseResult.data;
51+
if (webhookResult.error) {
52+
// Unexpected error. Most likely due to an error in Plain's webhook server or a bug in the SDK.
53+
// Treat this as a 500 response from Plain.
54+
console.error('Unexpected error:', webhookResult.error.message);
55+
res.status(500).send('Unexpected error');
56+
return;
57+
}
58+
59+
// webhookResult.data is now a typed object.
60+
const webhookBody = webhookResult.data;
2861

2962
// You can use the eventType to filter down to a specific event type
3063
if (webhookBody.payload.eventType === 'thread.thread_created') {
31-
console.log(webhookBody.payload.thread.id);
64+
console.log(`Thread created: ${webhookBody.payload.thread.id}`);
3265
}
3366

34-
res.status(200);
67+
// Respond with a 200 status code.
68+
res.status(200).send('Webhook received');
3569
});
3670
```
71+
72+
We strongly recommend verifying the webhook signature before processing the webhook body. This ensures that the webhook was sent by Plain and not a malicious third party. However, if you want to skip the verification, you can use the [`parsePlainWebhook` function](https://plain-typescript-sdk-docs.vercel.app/functions/parsePlainWebhook.html) instead.

0 commit comments

Comments
 (0)