Improve webhook client api and make script to register webhooks

This commit is contained in:
Dominic Ferrando
2026-06-26 14:53:56 -04:00
parent 62b651c476
commit b3e7d9a251
6 changed files with 146 additions and 25 deletions
+62 -4
View File
@@ -13,6 +13,7 @@ type ClientOptions = {
};
type Credentials = {
apiBaseUrl: string;
apiSitesUrl: string;
apiCollectionsUrl: string;
authHeader: Record<string, string>;
@@ -103,11 +104,11 @@ class ProductsClient {
method: "GET",
headers: this.creds.authHeader,
});
if (!res.ok) throw new WebflowError("Failed to get all Webflow products", res.status, await parsePayload(res));
if (!res.ok) throw new WebflowError("Failed to list Webflow products", res.status, await parsePayload(res));
const payload = (await res.json()) as Webflow.MetaDataMulti<"items", Webflow.Products.ProductAndSkus>;
allWebflowProducts.push(...payload.items);
offset = allWebflowProducts.length;
if (allWebflowProducts.length >= payload.pagination.total) break;
if (allWebflowProducts.length >= (payload?.pagination?.total ?? 0)) break;
} while (opt.forceAll);
return allWebflowProducts;
}
@@ -168,11 +169,11 @@ class OrdersClient {
method: "GET",
headers: this.creds.authHeader,
});
if (!res.ok) throw new WebflowError("Failed to get all Webflow orders", res.status, await parsePayload(res));
if (!res.ok) throw new WebflowError("Failed to list Webflow orders", res.status, await parsePayload(res));
const payload = (await res.json()) as Webflow.MetaDataMulti<"orders", Webflow.Orders.Order>;
allOrders.push(...payload.orders);
offset = allOrders.length;
if (allOrders.length >= payload.pagination.total) break;
if (allOrders.length >= (payload?.pagination?.total ?? 0)) break;
} while (opt.forceAll);
return allOrders;
}
@@ -213,6 +214,60 @@ class OrdersClient {
}
}
class WebhooksClient {
constructor(private creds: Credentials) { }
async list(opt: PagingOptions = {}): Promise<Webflow.Webhook.Config[]> {
const allWebhooks: Webflow.Webhook.Config[] = [];
let offset = opt.offset ?? 0;
do {
const res = await fetch(`${this.creds.apiSitesUrl}/webhooks?offset=${offset}&limit=${opt.limit ?? 100}`, {
method: "GET",
headers: this.creds.authHeader,
});
if (!res.ok) throw new WebflowError("Failed to list Webflow webhooks", res.status, await parsePayload(res));
const payload = (await res.json()) as Webflow.MetaDataMulti<"webhooks", Webflow.Webhook.Config>;
allWebhooks.push(...payload.webhooks);
offset = allWebhooks.length;
if (allWebhooks.length >= (payload?.pagination?.total ?? 0)) break;
} while (opt.forceAll);
return allWebhooks;
}
/**
* Limit of 75 registrations per event
*/
async create(url: string, event: Webflow.Webhook.Event) {
const res = await fetch(`${this.creds.apiSitesUrl}/webhooks`, {
method: "POST",
headers: {
"Content-Type": "application/json",
...this.creds.authHeader,
},
body: JSON.stringify({
"url": url,
"triggerType": event
}),
});
if (!res.ok) throw new WebflowError("Failed to create Webflow webhook", res.status, await parsePayload(res));
}
async remove(webhookId: string): Promise<void> {
const res = await fetch(
`${this.creds.apiBaseUrl}/webhooks/${webhookId}`,
{
method: "DELETE",
headers: {
"Content-Type": "application/json",
...this.creds.authHeader,
},
body: JSON.stringify({}),
},
);
if (!res.ok) throw new WebflowError("Failed to remove Webflow webhook", res.status, await parsePayload(res));
}
}
class UtilClient {
constructor(private webhookSecret: string) { }
@@ -248,16 +303,19 @@ class UtilClient {
export class WebflowClient {
readonly Products: ProductsClient;
readonly Orders: OrdersClient;
readonly Webhooks: WebhooksClient;
readonly Util: UtilClient;
constructor(options: ClientOptions) {
const creds: Credentials = {
apiBaseUrl: `https://api.webflow.com/v2`,
apiSitesUrl: `https://api.webflow.com/v2/sites/${options.siteId}`,
apiCollectionsUrl: `https://api.webflow.com/v2/collections/${options.collectionsId}`,
authHeader: { Authorization: `bearer ${options.token}` },
};
this.Products = new ProductsClient(creds);
this.Orders = new OrdersClient(creds);
this.Webhooks = new WebhooksClient(creds);
this.Util = new UtilClient(options.webhookSecret);
}
}