VayaFlow
Contacts

Submitting Contacts

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

Submitting Contacts

Contacts enter VayaFlow through the submission API endpoint. When a contact is submitted, it goes through a multi-step processing pipeline.

API Submission

Submit a contact using the POST /api/v1/contacts/submit endpoint:

curl -X POST https://api.vayaflow.com/api/v1/contacts/submit \
  -H "X-API-Key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "playbookId": "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
playbookIdstringThe playbook to submit the contact to
firstNamestringContact first name (trimmed, title-cased). Required for new contacts, optional when contactId is provided
lastNamestringContact last name (trimmed, title-cased). Required for new contacts, optional when contactId is provided
emailstringEmail address (lowercased). Required for new contacts, optional when contactId is provided
phonestringPhone number, minimum 10 digits. Required for new contacts, optional when contactId is provided

Optional Fields

FieldTypeDescription
contactIdstringExisting contact ID. When provided, the contact's existing data is used and the contact 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 (kept out of live lists, no pixel firing; do-not-contact and deduplication checks still run). Test-ness is never inferred from a name or email.
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 Contact type directly.

FieldTypeDescription
paramsobjectAll tracking parameters — UTMs, custom URL params, etc. Stored as-is on the contact. Defaults to {}
captureUrlstringURL where the contact was captured
referrerstringReferring URL
ipAddressstringContact's IP address (auto-captured from request if not provided)
userAgentstringContact'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 contact
trustedFormCertIdstringTrustedForm certificate ID
trustedFormCertUrlstringTrustedForm certificate URL
jornayaLeadIdstringJornaya LeadiD token
privacyPolicyUrlstringPrivacy policy URL shown to the contact
termsUrlstringTerms of service URL shown to the contact
customFieldsobjectAdditional compliance key-value data

Files

Attach file references to the contact.

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

Processing Pipeline

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

  1. Routing Rules — Evaluate which playbooks match the contact'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 playbook's endpoints
  8. Fallback — If rejected, try fallback playbooks

Response

A successful submission returns:

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

The contact will be processed asynchronously. Use the Get Contact Details endpoint to check the status.

On this page