Skip to main content

LeadSquared

The LeadSquared integration runs in two independent directions. Most accounts use both together, but each can be enabled on its own:

DirectionWhat happensSection
Inbound — LeadSquared → SprioA lead is created, or reassigned to a specific owner, and Sprio automatically places an outbound callAuto-call trigger
Outbound — Sprio → LeadSquaredAfter a Sprio call ends, a lead record is created/updated in LeadSquared with the call outcomePost-call lead push

Both use the same LeadSquared API credential (an Access Key + Secret Key pair, generated from LeadSquared's own Settings → API page — this is not something Sprio issues).


Inbound: Auto-call trigger

How it works

  1. You connect LeadSquared from Integrations → LeadSquared and choose which assistant should place the calls.
  2. Sprio registers two webhooks on your LeadSquared account via their native Webhook.svc/Create API — one for lead creation, one for owner reassignment (see why two below). This happens automatically; there's no manual webhook setup on your side.
  3. When either event fires, LeadSquared POSTs the lead's data to Sprio. Sprio validates the request, queues the lead, and — once the checks below pass — places a call using the assigned assistant, with the lead's name and details available to the assistant during the conversation.

Why two webhooks

LeadSquared's Webhook.svc/Create ties one webhook to exactly one WebhookEvent. In real usage, "a lead enters the account" almost always means an existing lead being reassigned to a specific owner (e.g. your sales team routes a lead to an "AI Calling" account when they want Sprio to call it) — not a brand-new lead being created. Registering only the creation event misses this entirely: a reassignment produces zero webhook traffic unless the owner-change event is also registered.

WebhookEventMeaningPayload shape
3Lead creationFlat — fields posted directly on the request body
4Lead owner changeWrapped — {"Before": {...}, "After": {...}}; Sprio reads After

Both webhooks point at the same URL and the same secret token; both feed the identical processing pipeline below.

Field detection

LeadSquared's field names are per-tenant configurable (different accounts name their phone/lead-id fields differently), so Sprio checks a list of common variants rather than requiring one fixed key:

What Sprio needsFields checked (case-insensitive)
Phone numberPhone, Mobile, MobileNumber, Mobile_Number, PhoneNumber, Phone_Number, ContactNumber, Contact_Number, mx_Alternate_Number, mx_Phone, mx_Mobile
Lead identifierProspectID, ProspectId, prospectid, Id, LeadId, RelatedProspectId
Owner identifierOwnerId, Owner
Context given to the assistantFirstName, LastName, EmailAddress, Source, City, mx_City, mx_Project_Name, Notes, ProspectStage

If the webhook payload is missing a phone number (or the owner ID, when an owner restriction is configured — see below), Sprio makes a fallback call to LeadSquared's LeadManagement.svc/Leads.GetById to fetch the full record.

LeadSquared's webhook API has no server-side filtering — a registered webhook fires for every lead across the entire account, with no way to scope it to "only leads owned by user X" at registration time. Without an app-level filter, turning on auto-call would call every new/reassigned lead org-wide.

Sprio's trigger_owner_user_id setting closes this gap: configure it to a specific LeadSquared user ID (e.g. a dedicated "AI Calling" account), and Sprio only places a call when the lead's owner matches — every other real lead is received, logged, and skipped (visible in your integration's Activity tab as owner_mismatch).

note

If you want true server-side scoping instead of an app-level filter, that requires building a custom Automation Workflow inside LeadSquared itself — a separate, LeadSquared-side mechanism you'd maintain independently. Most accounts find the app-level filter sufficient.

Dedup guarantees

  • Once per lead per day — the same lead ID won't trigger a second call the same day (IST). A lead re-entering tomorrow is treated as fresh.
  • Cross-assistant phone dedup — if any assistant on this connection has already dialed a phone number, no other assistant on the same connection will dial it again, even if the number arrives under a different lead ID.
  • Race-safe — both checks above are enforced by a database uniqueness constraint, not just a pre-check, so concurrent webhook deliveries (e.g. a bulk reassignment) can't double-dial.
  • Loop guard — a lead carrying one of your own platform phone numbers is never auto-called.

Known LeadSquared platform behavior

  • No signature scheme. Authenticity is the secret token header alone (X-Sprio-Webhook-Token, generated per connection). LeadSquared lets a webhook carry custom headers (CustomHeaders) — this is what carries the token.
  • Auto-disables after failures. LeadSquared disables a webhook after 10 consecutive delivery failures, so Sprio always acknowledges quickly (200 OK) before doing any real processing.
  • Validates the URL synchronously during registration. When a webhook is created, LeadSquared immediately fires a HEAD request, then a POST carrying the token, as part of validating the registration call itself — before Create even returns a response. Sprio's webhook route always answers these fast.
  • Delivery isn't instant. Expect roughly 5–10 minutes between a lead event happening in LeadSquared and the webhook actually arriving — this is LeadSquared's own dispatch latency, not something Sprio can speed up.

Outbound: Post-call lead push

After a call ends, Sprio can push the outcome back into LeadSquared as a lead record using Lead.Capture.

Field mapping

Field mapping is configured per connection. A typical setup:

LeadSquared fieldSource
FirstNameExtracted from the call (optional — sent blank if not captured, not skipped)
PhoneThe caller's number
EmailAddressA unique per-call placeholder (voice-lead-{call_id}@dummy.com) — avoids LeadSquared's email-based dedup colliding across different callers
SourceConfigurable literal, or conditional based on whether call details were captured
mx_Project_Name, mx_City, etc.Extracted from the call, if your extraction schema captures them
note

Field availability depends on your LeadSquared tenant's schema — fields like mx_Location that don't exist on your account will reject the whole push with a MXUnknownAttributeException. Confirm your field set with your LeadSquared admin before enabling a mapping.

Repeat callers and phone uniqueness

LeadSquared's own dedup behavior matters here:

  • Lead.Capture with SearchBy: Phone merges into the existing lead for a repeat caller rather than creating a new one — this is expected LeadSquared behavior (its response reports IsCreated: false), not a Sprio bug.
  • If your LeadSquared tenant enforces a unique Phone constraint, using Lead.Create (always creates) instead will fail for repeat callers with MXDuplicateEntryException. If you need every call to always create a brand-new lead record regardless of repeat callers, your LeadSquared admin needs to relax that constraint — there's no workaround on Sprio's side.

Templates and optional fields

Field values that use a {placeholder} template have no fallback — a call missing any referenced value aborts that entire push. Reserve templates for fields that are always populated (like the per-call email placeholder above); use plain extracted-field mapping for anything optional.


Setup checklist

  1. Get your Access Key and Secret Key from LeadSquared (Settings → API, on your LeadSquared account).
  2. In Sprio, go to Integrations → LeadSquared → Connect, and enter the credential.
  3. For inbound auto-calling: assign the assistant, set trigger_owner_user_id if you want owner-scoped filtering, and enable auto-call new leads.
  4. For outbound post-call push: configure field mapping and which call statuses should trigger a push.
  5. Send a test event from the connection page to confirm the whole pipeline before relying on real leads — see Testing.

Troubleshooting

SymptomLikely cause
Reassigning a lead's owner doesn't trigger a callConfirm both webhooks are armed (Integrations → LeadSquared connection detail shows webhook status) — a connection created before this was fixed may only have the creation webhook
A real lead is skipped with owner_mismatch in ActivityExpected if trigger_owner_user_id is set and the lead isn't owned by that user — this is the filter working as intended
No call after a lead event, no error eitherLeadSquared's own dispatch delay (5–10 min) — wait before assuming failure; check the connection's Activity tab for received-but-unprocessed events
Outbound push fails with MXUnknownAttributeExceptionA mapped field doesn't exist on your LeadSquared tenant's schema — remove or rename it in your field mapping
Outbound push fails with MXDuplicateEntryExceptionYour tenant enforces unique Phone and you're using Lead.Create — switch to Lead.Capture + SearchBy:Phone, or ask LeadSquared support to relax the constraint