Movoto Leads Webhook

Test the Movoto leads webhook endpoint. This shows the default expected payload shape - the endpoint accepts any shape as long as a field mapping targets it.

Endpoint

Pushes the contact to GHL inline and responds with the result.

API Config

Client

Loan Officer

Realtor

Request

Endpoint:
POST /api/v1/test-location-123/webhook/movoto/leads
Headers:
{
  "Content-Type": "application/json",
  "m4-connect-key": "[your-api-key]"
}
Body (Editable):

API Reference

Payload shape:

The nested shape above is the default expected shape and is what the built-in fallback field mapping targets. Every field is optional, and the endpoint isn't limited to this shape - the fields actually used to build the contact (name, email, phone, etc.) are whatever the resolved field mapping (configured in the configurator, or this default) points at. A location can be configured with a mapping that targets a completely different payload shape with no code changes.

Default Field Mapping:

  • leadId movoto_lead_id
  • client.firstName / client.lastName contact.first_name / contact.last_name
  • client.email contact.email (fallback external_id when no uniqueIdentifier is configured)
  • client.phone contact.phone
  • client.address.* contact.address1 / contact.city / contact.state / contact.postal_code
  • loanOfficer.* lo_assigned / lo_email / lo_phone
  • realtor.* realtor_assigned / realtor_email / realtor_phone

Processing:

  • Field mapping is resolved via ConfigurationClient.getMappings for the "movoto" sub-feature, falling back to the default mapping above.
  • Name/email/phone for the contact record are read back out of the resolved mapping output, checked against known aliases (e.g. contact.email then email) - not fixed payload fields - so a differently-shaped payload works as long as a mapping targets it.
  • external_id is built from the mapping response's uniqueIdentifier field list when configured (joining resolved values with _), falling back to the resolved email.
  • If the mapping response includes tags, they're added to sync_data.tags.
  • A pending ContactSyncRecord is upserted with sync_source: "Movoto" and sync_direction: "In".
  • The existing GHL contact sync workflow picks up the pending record asynchronously.

Sync vs Async:

/api/v1/[locationId]/webhook/movoto/leads (synchronous, default) pushes the contact to GHL inline and reflects the result in the response. /api/v1/[locationId]/webhook/movoto/async/leads shares the same validation and field-mapping logic but only inserts a PENDING record and returns immediately - the existing GHL contact sync workflow (~2-minute cron) delivers it later. Use the toggle above to test either.

Full Documentation:

See docs/API_MOVOTO_LEADS.md for the complete field mapping table, error codes, and cURL examples for both endpoints.