Webflow Integration with External Services via API/Zapier
Webflow provides official REST API for working with CMS collections, forms, orders, and users. This is one of most open no-code builders in terms of API: documentation is complete, authentication is standard, limits are reasonable.
Webflow API: Authentication and Basic Requests
Two authentication options:
- API Token — user's personal key, suitable for server integrations
- OAuth 2.0 — for public applications working with different users' accounts
For own website, API Token is enough. Generated in "Account Settings" → "API Access".
$client = Http::withHeaders([
'Authorization' => 'Bearer ' . config('services.webflow.token'),
'accept' => 'application/json',
]);
// List of sites
$sites = $client->get('https://api.webflow.com/v2/sites')->json('sites');
// Collections of specific site
$collections = $client
->get("https://api.webflow.com/v2/sites/{$siteId}/collections")
->json('collections');
Working with CMS Collections
Adding element to collection (e.g., new vacancy or article from external system):
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . config('services.webflow.token'),
'Content-Type' => 'application/json',
])->post("https://api.webflow.com/v2/collections/{$collectionId}/items", [
'fieldData' => [
'name' => 'New Article',
'slug' => 'novaya-statya',
'description' => 'Article text...',
'published-on' => '2024-01-15T10:00:00Z',
'_archived' => false,
'_draft' => false,
],
]);
$itemId = $response->json('id');
After creation, item is in draft. Separate request needed for publishing:
Http::withHeaders([
'Authorization' => 'Bearer ' . config('services.webflow.token'),
])->post("https://api.webflow.com/v2/collections/{$collectionId}/items/publish", [
'itemIds' => [$itemId],
]);
API v2 limits: 60 requests per minute per token. For bulk operations — add delay or batching.
Webhooks from Webflow
Webflow can send events to external URL. Available triggers: form_submission, site_publish, ecomm_new_order, ecomm_order_changed, cms_item_created, cms_item_changed, cms_item_deleted.
Webhook registration via API:
Http::withHeaders([
'Authorization' => 'Bearer ' . config('services.webflow.token'),
'Content-Type' => 'application/json',
])->post("https://api.webflow.com/v2/sites/{$siteId}/webhooks", [
'triggerType' => 'form_submission',
'url' => 'https://yoursite.com/api/webhooks/webflow',
]);
Webflow signs requests with X-Webflow-Signature header (HMAC-SHA256):
public function verifyWebflowSignature(Request $request): bool
{
$secret = config('services.webflow.webhook_secret');
$body = $request->getContent();
$signature = $request->header('X-Webflow-Signature');
$expected = hash_hmac('sha256', $body, $secret);
return hash_equals($expected, $signature);
}
Zapier: No-Code Integration
Zapier has official Webflow connector. Links Webflow events with thousands of services: Google Sheets, HubSpot, Mailchimp, Slack, Notion, etc.
Typical zap "Webflow New Form → Lead to HubSpot":
- Trigger: "Webflow → New Form Submission" → select site and form
- Action: "HubSpot → Create Contact" → field mapping
- (optional) Filter: only if
emailfield not empty
Zapier is polling-based for Webflow: checks every 15 minutes for new submissions. For urgent notifications — not acceptable, need direct webhook.
Alternative to Zapier for complex flows — n8n (self-hosted). Supports Webflow via HTTP nodes and has more flexible transformation logic without operation count limits.
CMS Synchronization with External Database
Pattern for syncing product catalog from ERP to Webflow CMS:
class SyncProductsToWebflow
{
public function handle(): void
{
$products = Product::where('updated_at', '>', $this->lastSync())->get();
foreach ($products as $product) {
$existing = $this->findWebflowItem($product->external_id);
if ($existing) {
$this->updateItem($existing['id'], $product);
} else {
$this->createItem($product);
}
}
$this->updateLastSync(now());
}
private function findWebflowItem(string $externalId): ?array
{
// Webflow doesn't support search by custom field via API directly,
// need to store mapping in local table
$mapping = WebflowItemMapping::where('external_id', $externalId)->first();
return $mapping ? ['id' => $mapping->webflow_id] : null;
}
}
Timelines
Simple integration via Zapier (form → CRM or table): 1–2 hours. CMS collection sync with external system via API: 1 business day. Full bidirectional sync with conflict handling: 2–3 business days.







