Enhanced Public Leads API

Create leads with automatic contact and property creation, duplicate detection, and Google Maps address validation in a single API call.

✨

What's Enhanced?

The enhanced leads API allows you to create complete leads with nested contact and property objects, eliminating the need for multiple API calls and providing intelligent duplicate handling.

Before (Traditional)

// 3 separate API calls required
const contact = await api.contacts.create({...});
const property = await api.properties.create({...});
const lead = await api.leads.create({
  contact_id: contact.id,
  property_id: property.id
});

After (Enhanced)

// Single API call with automatic handling
const result = await api.leads.create({
  contact: {...},
  property: {...},
  pipeline_id: "uuid"
});

Key Features

πŸ”

Automatic Duplicate Detection

Smart matching prevents duplicate contacts and properties. Returns existing records when matches are found.

πŸ—ΊοΈ

Google Maps Integration

Validates addresses, extracts components, and provides geocoding automatically using Google Places API.

πŸ”„

Backward Compatible

Existing integrations continue working unchanged. Enhanced features are completely optional.

⚑

Single API Call

Create complete leads with contacts and properties in one request. No more complex orchestration.

πŸ›‘οΈ

Comprehensive Validation

Field-level validation with detailed error messages and graceful fallback handling.

πŸ‘€

Automatic Agent Assignment

Leads are automatically assigned to agents based on territory, availability, and load balancing.

Quick Start

1

Get Your API Key

Obtain an API key with leads:create permission from your RoofIQ account settings.

2

Get Pipeline IDs

Retrieve your account's pipeline and stage IDs using the pipelines API.

GET /api/public/v1/pipelines
Authorization: Bearer your-api-key
3

Create Your First Enhanced Lead

const response = await fetch('/api/public/v1/leads', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    contact: {
      first_name: "John",
      last_name: "Doe",
      email: "john@example.com",
      mobile_number: "+1234567890"
    },
    property: {
      address: "123 Main St, Miami, FL",
      property_type: "Residential"
    },
    pipeline_id: "your-pipeline-id",
    pipeline_stage_id: "your-stage-id",
    source: "Your Integration"
  })
});

const result = await response.json();
console.log('Lead created:', result.results.lead.id);

Duplicate Detection

πŸ”

How It Works

The API automatically checks for existing records before creating new ones, ensuring clean data without manual deduplication.

Contact Matching

  • Email: Exact match (case-insensitive)
  • Phone: Fuzzy matching (digits only)
  • Scope: Within your account only

Property Matching

  • Address: Exact match after Google Maps normalization
  • Location: City + State + ZIP code combination
  • Scope: Within your account only

Example: Duplicate Detection Response

{
  "results": {
    "lead": {
      "id": "new-lead-uuid",
      "contact_id": "existing-contact-uuid",
      "property_id": "existing-property-uuid"
    },
    "creation_details": {
      "contact": {
        "created": false,  // Existing contact was used
        "data": null
      },
      "property": {
        "created": false,  // Existing property was used
        "data": null
      }
    }
  }
}

Google Maps Address Validation

πŸ—ΊοΈ

Automatic Address Enhancement

When you provide an address, the API automatically validates it with Google Maps and extracts standardized components.

Your Input

{
  "property": {
    "address": "123 main st miami fl"
  }
}
β†’

API Enhancement

{
  "property": {
    "address": "123 Main St",
    "city": "Miami",
    "state": "FL", 
    "zip_code": "33101",
    "country": "USA",
    "latitude": "25.7617",
    "longitude": "-80.1918",
    "google_validated_address": {...}
  }
}

What Gets Enhanced

  • βœ… Address formatting: Standardized street address
  • βœ… Component extraction: City, state, ZIP code
  • βœ… Geocoding: Latitude and longitude coordinates
  • βœ… Validation: Confirms address exists
  • βœ… Consistency: Same format as frontend forms

Voice360 Integration Example

πŸ“ž

Call Completion

Voice360 AI completes customer call

β†’
πŸ”„

Webhook Trigger

Your system receives call data

β†’
⚑

Lead Creation

Single API call creates complete lead

Implementation Example

// Voice360 webhook handler
app.post('/voice360/call-completed', async (req, res) => {
  const { customer, property, callDetails } = req.body;
  
  try {
    const leadResponse = await fetch('/api/public/v1/leads', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${ROOFIQ_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        contact: {
          first_name: customer.firstName,
          last_name: customer.lastName,
          email: customer.email,
          mobile_number: customer.phone
        },
        property: {
          address: property.address,
          property_type: "Residential"
        },
        pipeline_id: PIPELINE_ID,
        pipeline_stage_id: INITIAL_STAGE_ID,
        source: "Voice360",
        notes: `Call completed: ${callDetails.summary}`
      })
    });
    
    const result = await leadResponse.json();
    
    // Log creation details
    console.log('Lead created:', result.results.lead.id);
    console.log('Contact created:', result.results.creation_details.contact.created);
    console.log('Property created:', result.results.creation_details.property.created);
    
    res.json({ success: true, leadId: result.results.lead.id });
    
  } catch (error) {
    console.error('Lead creation failed:', error);
    res.status(500).json({ error: 'Lead creation failed' });
  }
});

API Reference

POST /api/public/v1/leads

Request Headers

Authorization: Bearer your-api-key
Content-Type: application/json

Request Body Schema

Field Type Required Description
contact object Yes* Contact information (alternative to contact_id)
contact_id uuid Yes* Existing contact ID (alternative to contact object)
property object No Property information (alternative to property_id)
property_id uuid No Existing property ID (alternative to property object)
pipeline_id uuid Yes Target pipeline for the lead
pipeline_stage_id uuid Yes Initial stage in the pipeline
source string No Lead source identifier
notes string No Additional notes about the lead

* Either contact or contact_id must be provided

Contact Object Schema

Field Type Required Description
first_name string Yes Contact's first name (1-100 characters)
last_name string Yes Contact's last name (1-100 characters)
email string Yes Valid email address
mobile_number string No Phone number (max 20 characters)
company string No Company name (max 200 characters)

Property Object Schema

Field Type Required Description
address string Yes Street address (1-500 characters)
city string No City name (auto-filled from Google Maps)
state string No State code (auto-filled from Google Maps)
zip_code string No ZIP code (auto-filled from Google Maps)
property_type enum No Residential, Commercial, Industrial, Multi-Family
square_footage integer No Property size in square feet
year_built integer No Year property was built (1800-2030)

Configuration

Environment Variables

# Optional - for Google Maps address validation
GOOGLE_MAPS_API_KEY=your-google-maps-api-key-here
ℹ️

Google Maps Setup

  1. Create a Google Cloud Platform project
  2. Enable the Geocoding API
  3. Create an API key with Geocoding API access
  4. Set the GOOGLE_MAPS_API_KEY environment variable
  5. The API works gracefully without Google Maps if not configured

Best Practices

πŸ” Monitor Creation Details

Always check the creation_details in responses to understand whether contacts and properties were created or existing ones were reused.

πŸ“§ Consistent Email Formats

Use consistent email formatting for reliable duplicate detection. The API is case-insensitive but exact matching works best.

🏠 Complete Addresses

Provide complete addresses including city and state for best Google Maps validation results. Partial addresses may not validate properly.

πŸ”§ Error Handling

Implement proper error handling for validation failures, network issues, and API rate limits. Always check response status codes.

πŸ“Š Logging & Monitoring

Log creation details to track whether contacts/properties are being created vs reused. Monitor for unexpected duplicate rates.

πŸ§ͺ Testing

Test with real addresses to verify Google Maps integration. Use different email addresses to test duplicate detection.