LeadSail
Leads

Submitting Leads

How to submit leads via the API and understand the engine processing flow.

Submitting Leads

Leads enter LeadSail through the submission API endpoint. When a lead is submitted, it goes through a multi-step processing pipeline.

API Submission

Submit a lead using the POST /api/v1/leads/submit endpoint:

curl -X POST https://api.leadsail.app/api/v1/leads/submit \
  -H "X-API-Key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "campaignId": "cmp_abc123",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane@example.com",
    "phone": "+15559876543",
    "address": {
      "street": "123 Main St",
      "city": "Los Angeles",
      "state": "CA",
      "zip": "90210"
    }
  }'

Request Body

The schema uses strict validation — unknown fields are rejected.

Required Fields

FieldTypeDescription
campaignIdstringThe campaign to submit the lead to
firstNamestringContact first name (trimmed, title-cased). Required for new leads, optional when leadId is provided
lastNamestringContact last name (trimmed, title-cased). Required for new leads, optional when leadId is provided
emailstringEmail address (lowercased). Required for new leads, optional when leadId is provided
phonestringPhone number, minimum 10 digits. Required for new leads, optional when leadId is provided

Optional Fields

FieldTypeDescription
leadIdstringExisting lead ID. When provided, the lead's existing data is used and the lead is re-submitted through the qualification engine. Contact fields become optional
addressobjectSee Address below
dateOfBirthstringFormat: YYYY-MM-DD
countrystring2-letter uppercase ISO code (e.g., US, CA)
questionnaireobject or arraySee Questionnaire below. Defaults to {}
customFieldsobjectArbitrary key-value pairs
attributionobjectSee Attribution below
complianceobjectSee Compliance below
filesarraySee Files below
isTestbooleanFlag as a test record (skips deduplication and pixel firing)
timezonestringIANA timezone string (e.g., America/New_York)
notesstringFree-text notes

Address

All address fields are required when address is provided, except unit and country.

FieldTypeDescription
streetstringStreet address
unitstringUnit/apartment number (optional)
citystringCity
statestring2-letter uppercase state code (e.g., CA, NY)
zipstring5 or 9 digit ZIP code (e.g., 90210 or 90210-1234)
countrystring2-letter uppercase ISO code. Defaults to US (optional)

Questionnaire

Accepts two formats:

Object format — keys are mapped to question labels via your field library. If a key doesn't exist in the library, the key name is used as the label.

{
  "dob": "1990-01-15",
  "injury_type": "car_accident"
}

Array format — you provide the question labels directly.

[
  { "key": "dob", "question": "Date of Birth", "answer": "1990-01-15" },
  { "key": "injury_type", "question": "Type of Injury", "answer": "car_accident" }
]
FieldTypeDescription
keystringField identifier (required)
questionstringDisplay label for the field (required)
answeranyThe answer value (required)

Attribution

Track marketing source and ad platform data. The attribution structure mirrors the internal Lead type directly.

FieldTypeDescription
paramsobjectAll tracking parameters — UTMs, custom URL params, etc. Stored as-is on the lead. Defaults to {}
captureUrlstringURL where the lead was captured
referrerstringReferring URL
ipAddressstringLead's IP address (auto-captured from request if not provided)
userAgentstringLead's browser user agent (auto-captured from request if not provided)
gclidstringGoogle Ads click ID
gbraidstringGoogle Ads app click ID
wbraidstringGoogle Ads web-to-app click ID
fbclidstringFacebook click ID
fbcstringFacebook browser cookie
fbpstringFacebook pixel cookie
ttclidstringTikTok click ID
ttpstringTikTok pixel cookie
msclkidstringMicrosoft Ads click ID
tblcistringTaboola click ID
adPlatformstringAd platform name (auto-detected from click IDs if not provided)
capturePlatformstringCapture platform name

Example attribution object:

{
  "params": {
    "utm_source": "facebook",
    "utm_medium": "paid_social",
    "utm_campaign": "spring_2024",
    "custom_tracking_id": "abc123"
  },
  "fbclid": "fbclid_xyz789",
  "captureUrl": "https://example.com/landing"
}

Compliance

TCPA consent and verification data.

FieldTypeDescription
tcpaConsentbooleanWhether TCPA consent was given
tcpaConsentTimestampstringISO 8601 datetime of consent
tcpaConsentMethodstringOne of: checkbox, signature, sms_optin, voice_recording
tcpaLanguagestringTCPA consent language shown to the lead
trustedFormCertIdstringTrustedForm certificate ID
trustedFormCertUrlstringTrustedForm certificate URL
jornayaLeadIdstringJornaya LeadiD token
privacyPolicyUrlstringPrivacy policy URL shown to the lead
termsUrlstringTerms of service URL shown to the lead
customFieldsobjectAdditional compliance key-value data

Files

Attach file references to the lead.

FieldTypeDescription
sourceKeystringIdentifier for the file source (required)
fileUrlstringURL where the file is hosted (required)
typestringFile type/category
metadataobjectAdditional file metadata

Processing Pipeline

When a lead is submitted, the qualification engine processes it through these steps:

  1. Routing Rules — Evaluate which campaigns match the lead's data
  2. Disqualification Conditionals — Check for hard DQ conditions (e.g., excluded states)
  3. Dynamic Keys — Apply dynamic field transformations
  4. Required Fields — Verify all required fields are present
  5. Field Qualification — AI-powered validation of field values
  6. Payload Building — Construct the delivery payload
  7. Delivery — Send to the campaign's endpoints
  8. Fallback — If rejected, try fallback campaigns

Response

A successful submission returns:

{
  "success": true,
  "leadId": "lead_abc123",
  "submissionId": "sub_def456",
  "submissionNumber": 1,
  "message": "Lead submitted for processing",
  "timestamp": "2024-01-15T10:30:00.000Z"
}

The lead will be processed asynchronously. Use the Get Lead Details endpoint to check the status.

On this page