Files
nur-falah/deploy/n8n-polar-to-twenty.json
wmj feb5f1f03b feat: add Bir Nur (Well of Light) waqf dashboard + reframe Support with bank trustee giving model
- New BirNur.svelte: waqf configuration based on companions' model
- Reframed Support.svelte with dual-track: bank trustee giving + app support
- Updated App.svelte to add Waqf tab (tab 14) between WorshipTracker and Support
- Model inspired by Uthman's Well of Rumah and Abdur Rahman bin Auf's productive endowment
2026-08-08 16:54:51 +08:00

233 lines
7.6 KiB
JSON

{
"name": "Polar.sh → Twenty CRM Sync",
"nodes": [
{
"id": "webhook-trigger",
"name": "Polar Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [250, 300],
"webhookId": "polar-twenty-sync",
"authentication": "none",
"properties": {
"httpMethod": "POST",
"path": "polar-webhook",
"responseMode": "onReceived",
"responseData": "",
"options": {}
},
"notes": "SET ME: Configure this webhook URL in Polar.sh dashboard under Webhooks → Add endpoint. Polar sends checkout.created, checkout.updated, checkout.succeeded events."
},
{
"id": "code-parse",
"name": "Parse Polar Payload",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [450, 300],
"properties": {
"language": "javaScript",
"code": "// Parse Polar.sh webhook payload\n// Polar sends: type, data (containing checkout object)\n// Checkout object has: customer (email, name, billingAddress), product (name, metadata), amount, currency\n\nconst payload = $input.first().json;\nconst eventType = payload.type || '';\nconst checkout = payload.data || {};\n\n// Extract fields from Polar payload\nconst email = checkout.customer?.email || checkout.customerEmail || '';\nconst name = checkout.customer?.name || checkout.customerName || '';\nconst amount = checkout.amount || 0;\nconst currency = checkout.currency || 'usd';\nconst productName = checkout.product?.name || checkout.productName || '';\nconst metadata = checkout.product?.metadata || checkout.metadata || {};\nconst donationType = metadata.donationType || metadata.type || '';\nconst timestamp = checkout.createdAt || new Date().toISOString();\nconst polarCheckoutId = checkout.id || '';\n\n// Map donation type\nlet donationLabel = '';\nif (donationType === 'sadaqah' || productName.toLowerCase().includes('sadaqah')) {\n donationLabel = 'Sadaqah';\n} else if (donationType === 'zakat' || productName.toLowerCase().includes('zakat')) {\n donationLabel = 'Zakat';\n} else if (donationType === 'hibah' || productName.toLowerCase().includes('hibah')) {\n donationLabel = 'Hibah';\n} else {\n donationLabel = 'Donation';\n}\n\n// Format amount to display value (cents to main unit)\nconst amountDisplay = currency === 'myr' ?\n `RM${(amount / 100).toFixed(2)}` :\n `${(amount / 100).toFixed(2)} ${currency.toUpperCase()}`;\n\nreturn {\n email,\n name,\n amount,\n amountDisplay,\n currency,\n donationLabel,\n donationType,\n productName,\n polarCheckoutId,\n timestamp\n};"
},
"notes": "Extracts and normalises Polar.sh webhook fields. Metadata fields are set in Polar product configuration."
},
{
"id": "http-twenty",
"name": "Twenty CRM - Upsert Contact",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [650, 300],
"credentials": {
"httpRequest": {
"id": "SET_ME_TwentyCRMApiKeyId",
"name": "Twenty CRM API Key"
}
},
"properties": {
"method": "POST",
"url": "SET_ME_TwentyCRMAPIUrl/rest/contacts",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "email",
"value": "={{ $json.email }}"
},
{
"name": "name",
"value": "={{ $json.name }}"
},
{
"name": "city",
"value": ""
},
{
"name": "phone",
"value": ""
},
{
"name": "position",
"value": "={{ $json.donationLabel }}"
},
{
"name": "linkedinLink",
"value": ""
},
{
"name": "xLink",
"value": ""
},
{
"name": "introduction",
"value": ""
}
]
},
"options": {
"timeout": 10000,
"allowUnauthorizedCerts": false,
"redirect": {},
"response": {
"response": {
"responseFormat": "json"
}
}
},
"headers": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"notes": "SET ME: Replace the URL placeholder with your Twenty CRM instance URL (e.g., https://your-workspace.twenty.com). Configure the header auth credential with your Twenty CRM API key."
},
{
"id": "set-activity",
"name": "Twenty CRM - Log Note Activity",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [650, 480],
"credentials": {
"httpRequest": {
"id": "SET_ME_TwentyCRMApiKeyId",
"name": "Twenty CRM API Key"
}
},
"properties": {
"method": "POST",
"url": "SET_ME_TwentyCRMAPIUrl/rest/activityTargets",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "title",
"value": "={{ $json.donationLabel + ' Donation - ' + $json.amountDisplay }}"
},
{
"name": "body",
"value": "={{ 'Donation from ' + $json.name + ' (' + $json.email + ')\\n' + 'Type: ' + $json.donationLabel + '\\n' + 'Amount: ' + $json.amountDisplay + '\\n' + 'Checkout ID: ' + $json.polarCheckoutId + '\\n' + 'Date: ' + $json.timestamp }}"
},
{
"name": "type",
"value": "Note"
},
{
"name": "visibility",
"value": "workspace"
}
]
},
"options": {
"timeout": 10000,
"allowUnauthorizedCerts": false,
"redirect": {},
"response": {
"responseFormat": "json"
}
},
"headers": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"notes": "SET ME: Same credential and URL base as above. This node logs a note activity for the contact."
},
{
"id": "noop-complete",
"name": "Done",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [850, 300],
"properties": {}
}
],
"connections": {
"Polar Webhook": {
"main": [
[
{
"node": "Parse Polar Payload",
"type": "main",
"index": 0
}
]
]
},
"Parse Polar Payload": {
"main": [
[
{
"node": "Twenty CRM - Upsert Contact",
"type": "main",
"index": 0
},
{
"node": "Twenty CRM - Log Note Activity",
"type": "main",
"index": 0
}
]
]
},
"Twenty CRM - Upsert Contact": {
"main": [
[
{
"node": "Done",
"type": "main",
"index": 0
}
]
]
},
"Twenty CRM - Log Note Activity": {
"main": [
[
{
"node": "Done",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"versionId": "1.0.0"
}