Rules:
- Create the webhook in the intermediary (Make/n8n/custom)
- Method: POST
- Public HTTPS URL (this URL will be the crmAccessToken in LinkedScope).
- The endpoint must accept the auth header (this value will be the crmSecretToken in LinkedScope).
- The body received from LinkedScope is empty (null / no payload).
- Implement auth validation in the intermediary
- Read req.headers.auth.
- If different from the expected token, return 401/403.
- If valid, continue with the CRM query.
- Fetch deals from the CRM and map them to the expected format
- Your intermediary flow must call the desired CRM endpoints and return open deals (open/created date) from the last 24 months
- Build a pure JSON array (not an object with deals)
- Required return: HTTP 200 + application/json + […]
- Expected JSON response structure
- The root must be an array: [ {deal1}, {deal2} ]
- Recommended fields per deal:
- dealName, dealLink, companyName, createdAt, dealStage, dealValue
- Identification fields (strongly recommended):
- linkedinCompanyId or companyUrn / company_urn
- optional: linkedinCompanyUrl (/company/123 or /company/slug)
- Status:
- isWon: true | false | null
- Also accepts strings such as won/lost/closedwon/closedlost
Practical example:
[
{
"dealId": "D-1001",
"dealName": "Enterprise Plan",
"dealLink": "https://crm.example.com/deals/D-1001",
"pipeline": "Sales",
"ownerName": "Ana Silva",
"ownerEmail": "[email protected]",
"companyName": "ACME",
"companyDomain": "acme.com",
"linkedinCompanyId": "89482395",
"dealStage": "Proposal sent",
"dealValue": 15000,
"createdAt": "2025-11-01T10:23:00Z",
"closedAt": null,
"isWon": null
}
]- Configure in LinkedScope (Settings > Integrations > Any CRM)
- Field 1 (trigger/webhook URL): URL of the intermediary webhook.
- Field 2 (token): shared secret.
- Save. The backend validates by calling the webhook (dummyFetch).
- Validation and synchronization
- If webhook/auth fails on save: credential error (CRM Credentials Error).
- With the connection saved, LinkedScope uses this webhook to load deals/users/stages.
- Optional: trigger a manual sync via POST /api/v1/crm-sync/invoke (authenticated).
- Common error checklist
- Returning { deals: […] } instead of […] → incorrect.
- If you do not send ownerName / ownerEmail / dealStage → users/stages may appear incomplete or empty.
- URL without http/https → blocked in the UI.
- Empty token → the ANY integration may return empty results.
Webhook response requirements:
- The response must be a JSON array ([ … ]), not an object.
- Return open deals from the last 24 months (2 years) for a better experience.
- Technically the parser accepts deals with missing fields (fallback logic is applied), so the “hard required per deal” fields are minimal.
- In practice, for proper functionality, return at least:
- dealName, dealLink, companyName, createdAt, dealStage, dealValue
- Highly recommended:
- id/dealId/deal_id (dedupe)
- linkedinCompanyId or companyUrn (better matching)
- ownerName and ownerEmail (owners/listings)