API Overview
Webhooks

CallRail Webhooks

Connect CallRail to MoveRight with two webhook endpoints. The precall webhook fires when a call rings in — creating a lead and logging the call before your agent picks up. The postcall webhook fires after the call ends — updating attribution data and appending call details to the job timeline.

Overview

Precall webhook

POST /api/callrail/precall

Postcall webhook

POST /api/callrail/postcall

MoveRight receives real-time call data from CallRail via two webhook endpoints. Both endpoints accept application/x-www-form-urlencoded bodies (the default CallRail format) and resolve the MoveRight zone from the request context.

Together, the two webhooks provide a complete call-to-lead pipeline:

  1. 1 A caller dials your CallRail tracking number
  2. 2 CallRail fires the <strong>precall webhook</strong> before the phone rings at your office
  3. 3 MoveRight matches the caller to an existing job (by phone number) or creates a new lead
  4. 4 An "Inbound Call" comment appears on the job timeline in real time
  5. 5 After the call ends, CallRail fires the <strong>postcall webhook</strong> with full attribution data (recording URL, UTM params, duration, transcription)
  6. 6 MoveRight appends the call details and marketing source data to the job
Idempotency: The CallRail id field is stored as an externalMessageID on the inbound call comment. If CallRail sends the same call event twice (e.g., retries), MoveRight deduplicates by this ID rather than creating a duplicate comment thread.

Setup in CallRail

In your CallRail account, create two webhooks:

  1. 1

    Go to Settings → Integrations → Webhooks

    Create a new webhook for each event type.

  2. 2

    Precall webhook

    Set the URL to <code>https://moveright.app/api/callrail/precall?zone=YOUR_ZONE_ID</code> and select the "Before Call Connected" trigger. This fires when a call starts ringing, before anyone picks up.

  3. 3

    Postcall webhook

    Set the URL to <code>https://moveright.app/api/callrail/postcall?zone=YOUR_ZONE_ID</code> and select the "Call Ended" trigger. This fires after the call completes, with full attribution data.

  4. 4

    Enable CallRail in MoveRight

    In your MoveRight zone settings, set <code>callrail.enabled</code> to <code>true</code>. See <a href="#zone-config" class="text-brand-green hover:underline">Zone Configuration</a> for all available settings.

Important: The zone query parameter is required. CallRail does not send zone information in the webhook body — it must be embedded in the URL you configure in CallRail. Use the MoveRight zone ID for the franchise location that owns the tracking number.

Precall Webhook

Endpoint

POST /api/callrail/precall?zone=ZONE_ID

Content-Type

application/x-www-form-urlencoded

The precall webhook fires before the phone rings at your office. It is designed to be fast — MoveRight returns 200 OK immediately and processes everything asynchronously so CallRail never times out.

When a call comes in, MoveRight:

  1. 1 Looks up the caller by phone number to find an existing job
  2. 2 If no job exists and <code>callrail.createJobInPrecall</code> is enabled, creates a new lead job using the caller's data
  3. 3 If a job already exists, updates its marketing source/origin data (without overwriting existing values)
  4. 4 Adds an "Inbound Call" comment to the job with the CallRail call ID for thread tracking

Precall Responses

Status Condition Description
200 Missing phone Returned immediately. Processing happens asynchronously after the response is sent.
400 Missing phone The <code>customer_phone_number</code> field is missing or empty.

Postcall Webhook

Endpoint

POST /api/callrail/postcall?zone=ZONE_ID

Content-Type

application/x-www-form-urlencoded

The postcall webhook fires after the call ends and includes the full set of call data: recording URL, duration, transcription, UTM attribution, and more.

When MoveRight receives a postcall webhook:

  1. 1 Looks up the caller by phone number to find the existing job
  2. 2 If no job is found, returns <code>"NO JOB"</code> and exits
  3. 3 If CallRail is not enabled for the zone, returns <code>"CALLRAIL NOT ENABLED IN JOB ZONE"</code>
  4. 4 If <code>callrail.postCallUpdateSource</code> is enabled, parses UTM/attribution data and updates the job's source (without overwriting existing values)
  5. 5 Appends a comment to the existing precall thread (or creates a new one) with the call details, tracking number, and source data

Postcall Responses

Status Body Condition
200 (empty) Call processed successfully
200 NO JOB No existing job found for the caller's phone number
200 CALLRAIL NOT ENABLED… The <code>callrail.enabled</code> zone config is false
400 (empty) The <code>customer_phone_number</code> field is missing or empty

Request Fields

Both webhooks accept the same payload — the standard CallRail webhook body. Only customer_phone_number is required. The full field list is documented below for reference; you don't need to send all fields.

Required fields

Field Required Description
customer_phone_number Yes The caller's phone number in E.164 format (e.g., <code>+17035550123</code>). Used to match against existing customers in MoveRight and as the primary phone number for new leads.
id Recommended CallRail's unique call identifier. Stored as <code>externalMessageID</code> for deduplication — if CallRail retries the same webhook, MoveRight updates the existing record rather than creating a duplicate.
direction Recommended <code>"inbound"</code> or <code>"outbound"</code>. Stored on the call thread for filtering.

Caller identification

Field Description
customer_name Caller name from caller ID. MoveRight uses AI to parse this into given/family name for new leads. Handles formats like "Last, First" and filters out "Wireless Caller" / "Unavailable".
customer_city Caller's city, inferred from area code or geolocation.
customer_state Caller's state or province code (e.g., "OH", "ON").
customer_country Two-letter country code (e.g., "US", "CA").
source_name Human-readable tracking source name (e.g., "Google Ads", "Bing"). Used as the referral source when creating a new lead.
business_phone_number The tracking number the caller dialed (E.164 format). Stored in call metadata.

Call details

Field Description
call_type Type of call: <code>"abandonded"</code>, <code>"answered"</code>, <code>"in_progress"</code>, <code>"missed"</code>, <code>"outbound"</code>, <code>"voicemail"</code>, or <code>"voicemail_transcription"</code>.
answered Whether the call was answered (<code>boolean</code>).
duration Call duration in seconds (as a string).
recording URL to the call recording audio file.
transcription Full call transcription text.
voicemail Whether the call ended in voicemail (<code>boolean</code>).
note Any notes attached to the call in CallRail.
tags / detail_tags Array of tag names applied to the call.
agent_email Email of the MoveRight agent who answered, if known.
spam Whether CallRail flagged the call as spam (<code>boolean</code>).
first_call Whether this is the caller's first call to this company (<code>boolean</code>).
total_calls Total number of calls from this customer (number).
start_time ISO 8601 timestamp when the call started.
created_at ISO 8601 timestamp when the CallRail record was created.

Marketing attribution

These fields are captured by CallRail from the caller's web session and mapped to MoveRight job source data. See Attribution Mapping for how each field is used.

Field Description
utm_source UTM source parameter (e.g., "google", "bing").
utm_medium UTM medium parameter (e.g., "cpc", "organic").
utm_campaign UTM campaign name. Fallback: <code>campaign</code> or <code>milestones.last_touch.campaign</code>.
utm_term UTM term/keyword. Fallback: <code>keywords</code> or <code>milestones.last_touch.keywords</code>.
utm_content UTM content parameter.
gclid Google Click ID for Google Ads attribution.
fbclid Facebook Click ID.
landing_page_url The page URL the caller was on when they dialed.
referrer_domain The domain of the referring site (e.g., "google.com").
source Raw source identifier from CallRail.
medium Marketing medium (e.g., "cpc", "organic").
keywords Keywords associated with the call.
campaign Campaign name tied to the call.
callsource CallRail source label — often the ad network or extension name.

AI and sentiment

Field Description
call_summary AI-generated summary of the call.
conversational_transcript Full conversational transcript with speaker labels.
sentiment Auto-scored sentiment label.
speaker_percent Object mapping speaker labels to percentage of time spoken.
call_highlights Key moments identified in the call.
keywords_spotted Keywords spotted during transcription.

Company and tracking

Field Description
company_id Numeric ID of the company within CallRail.
company_name Name of the company.
company_time_zone Company timezone in IANA format (e.g., "America/New_York").
tracking_phone_number The tracking number dialed (E.164 format).
formatted_tracking_phone_number Tracking number formatted for display.
formatted_customer_phone_number Customer number formatted for display.
lead_status Lead quality status: "good_lead", "not_a_lead", etc.
value Assigned monetary value of the call.
timeline_url URL to view the lead's timeline in CallRail.
Legacy fields: CallRail also sends legacy query-string fields (callercity, callercountry, callername, callernum, callerstate, callsource, datetime, destinationnum, ip, kissmetrics_id, landingpage, referrer, referrermedium, score, tag, trackingnum, timestamp, and resource_id variants). These are accepted for backward compatibility but the structured fields above are preferred.

Attribution Mapping

MoveRight maps CallRail webhook fields to internal job source data. Source data is never overwritten — if a job already has source data from an earlier touchpoint, the CallRail data is skipped for those fields.

MoveRight field CallRail field Notes
entry_gclid gclid Google Click ID for Ads attribution
entry_current_url landing_page_url Page the caller was on
entry_referring_domain referrer_domain Domain of referring site
entry_utm_source utm_source
entry_utm_medium utm_medium
entry_utm_campaign utm_campaign Fallback: <code>campaign</code> then <code>milestones.last_touch.campaign</code>
entry_utm_term utm_term Fallback: <code>keywords</code> then <code>milestones.last_touch.keywords</code>
entry_utm_content utm_content
entry_gad_source callsource Ad network or extension name
session_ip ip Caller's IP address

Zone Configuration

CallRail integration is controlled per zone (franchise location) through zone settings. Configure these in MoveRight under Settings → Business → CallRail.

Setting Default Description
callrail.enabled false Master switch. When false, both webhooks return early without processing.
callrail.createJobInPrecall false When true and no existing job is found, the precall webhook creates a new lead job automatically. When false, only the postcall webhook can create jobs (if the call comes through the datadip endpoint).
callrail.postCallUpdateSource false When true, the postcall webhook updates the job's marketing source data (UTM params, GCLID, etc.) without overwriting existing values.
callrail.defaultSource (none) Fallback source name used when CallRail doesn't provide one. Examples: "Google Ads", "Bing", "Organic".
callrail.defaultOrigin (none) Fallback origin used when CallRail doesn't provide one. Examples: "Web", "Phone", "Referral".
openai.parseCallRailCallerIdPrompt "Turn this caller ID into a first and last name…" The AI prompt used to parse caller ID names like "SMITH, JOHN Q" into structured first/last names for new leads.

cURL Example

Simulate a CallRail postcall webhook with curl:

curl -X POST \
  "https://moveright.app/api/callrail/postcall?zone=YOUR_ZONE_ID" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "id=call-12345" \
  -d "customer_phone_number=%2B17035550123" \
  -d "customer_name=Alice+Wonderland" \
  -d "direction=inbound" \
  -d "call_type=answered" \
  -d "answered=true" \
  -d "duration=180" \
  -d "tracking_phone_number=%2B18005551212" \
  -d "source_name=Google+Ads" \
  -d "utm_source=google" \
  -d "utm_medium=cpc" \
  -d "utm_campaign=fall-move-promo" \
  -d "utm_term=moving+company+near+me" \
  -d "gclid=CjwKCAjw-ZCDBhBQEiw" \
  -d "landing_page_url=https://example.com/movers" \
  -d "referrer_domain=google.com" \
  -d "recording=https://cdn.callrail.com/recordings/call-12345.mp3"   -d "transcription=Hi+I+need+help+with+a+move+next+week"
Tip: CallRail sends data as application/x-www-form-urlencoded by default. If you configure your webhook in CallRail to use JSON, it will also work — the endpoint accepts both formats.

Common Use Cases

Speed-to-lead automation

When <code>callrail.createJobInPrecall</code> is enabled, inbound calls automatically create a lead job before anyone picks up the phone. Your team sees the customer's name, number, and call source instantly in the MoveRight activity feed — no manual data entry.

Marketing attribution for phone calls

The postcall webhook captures UTM parameters, GCLID, and referrer data from every call. MoveRight stores this on the job so you can trace revenue back to specific ad campaigns, keywords, and landing pages — even for phone conversions.

Unified call timeline

Every call creates an "Inbound Call" comment thread on the job. The precall creates the initial comment, and the postcall appends call details (duration, recording, transcription, tracking number) to the same thread. Your team sees the full call story in one place.

CallRail + Datadip for screen pop

Use the <a href="/docs/api/datadip/" class="text-brand-green hover:underline">Datadip Voice Endpoint</a> alongside CallRail webhooks. Datadip runs during the call for real-time screen pop data, while CallRail webhooks handle lead creation and post-call attribution. They work together seamlessly — Datadip creates the inbound call comment, and the CallRail postcall appends to the same thread.