API Overview
Voice / IVR

Datadip Voice Endpoint

Connect any external phone system — Avoca AI, custom IVR, or any call platform — to MoveRight. When a call comes in, POST the caller's information to this endpoint. MoveRight matches the caller to an existing job or creates a new lead automatically, and returns full job context for your IVR to use.

Overview

Method

POST

Endpoint

https://moveright.app/api/datadip/voice?zone=ZONE_ID

The Datadip endpoint is designed to be called during a live inbound call before your IVR connects the caller to an agent. It performs a real-time data lookup against MoveRight:

  1. 1 Searches for an existing customer by caller phone number
  2. 2 If found, pulls the most recent open job for that customer
  3. 3 If not found, creates a new customer and lead job automatically
  4. 4 Returns the full job context — customer name, move addresses, timeline, call history, inventory, and Bee AI configuration — so your IVR can read it out to the agent before connecting
  5. 5 Creates an inbound call comment on the job for tracking
Idempotency: If you POST the same id twice (e.g., a call with multiple legs), MoveRight deduplicates by externalMessageID and returns the existing job rather than creating a duplicate. The second call updates the existing comment thread.

Request Format

Send a JSON POST body with the caller and call metadata. The zone query parameter is required and identifies which MoveRight zone (franchise location) should receive the lead.

POST https://moveright.app/api/datadip/voice?zone=YOUR_ZONE_ID
Content-Type: application/json
Authorization: Basic your@email.com:yourpassword

{
  "id": "unique-call-id-from-your-phone-system",
  "direction": "inbound",
  "origin": "Avoca",
  "tags": ["Avoca"],
  "url": "https://yourplatform.ai/call/unique-call-id",
  "note": "New inbound call",
  "called_phone_number": "+18005551212",
  "caller_name": "Alice Wonderland",
  "caller_phone_number": "+17035550123",
  "caller_country": "US",
  "caller_state": "OH",
  "caller_city": "Toledo",
  "caller_zip": "43607"
}

Input Fields

Field Required Description
id Yes Unique identifier for this call from your phone system. Used as the externalMessageID for deduplication — submitting the same id twice updates the existing record rather than creating a duplicate.
caller_phone_number Yes The caller's phone number in E.164 format, e.g. +17035550123. Used to match against existing customers in MoveRight.
called_phone_number No Your business phone number that was dialed, e.g. +18005551212. Stored in the call record.
direction No "inbound" or "outbound". Stored on the call thread. Default: "inbound".
caller_name No Caller's name from your phone system (e.g. caller ID). Used to pre-fill the customer name if a new lead is created.
origin No Human-readable label for the integration source, e.g. "Avoca", "IVR", "My Phone System". Stored as jobOrigin on new jobs. Appears in the MoveRight activity feed.
tags No Array of tag names to apply to a newly created job. Example: ["Avoca", "Speed-to-Lead"].
url No URL to the call record in your external platform. Stored in the call thread for easy cross-referencing.
note No Short description of the call. Shown in the inbound call comment on the job.
caller_country No Two-letter country code, e.g. "US", "CA". Used for zone-area matching.
caller_state No State or province, e.g. "OH", "ON". Used for zone-area matching.
caller_city No City name. Stored in call metadata.
caller_zip No Zip or postal code. Used as the origin area code when creating a new lead. Stored in call metadata.

Authentication

The Datadip endpoint uses the same authentication as the GraphQL API. For server-to-server calls from a phone platform, Basic auth is the simplest approach:

Authorization: Basic your@email.com:yourpassword

For production integrations, we recommend using a dedicated MoveRight service account with the minimum required permissions. See the Authentication docs for refresh token and JWT options.

Response Shape

The response always returns JSON with the following top-level fields. The most important difference between a new job and an existing job is the newJob: true flag.

Field Description
job The full job object for the matched or newly created job. Key fields: id, code, stage, state, total, currency, timeline, users, tags.
customer The customer user object: userId, givenName, familyName, phone, email, role.
comment The inbound call comment that was created on the job timeline.
inboundCall The inbound call thread object with all call metadata stored in MoveRight.
comments Array of all recent comment threads on the job, in markdown-formatted and raw form.
mdThreads All recent job activity as a single markdown string — useful for reading out to an AI agent or IVR.
timezone The timezone of the resolved zone, e.g. "America/New_York".
config Zone branding and AI configuration: companyName, aiName, businessHours, aiVoice.
fullInventory The job's inventory: rooms, specialtyItems, totalBoxes, totalWeight, totalVolume.
simpleInventory Human-readable inventory summary string, e.g. "3BR house, piano, 2 bikes".
fields Custom field values set on the job.
newJob Boolean. true if this call created a new customer and job; false if an existing job was matched.

Using the response in an IVR or AI agent

The mdThreads field is specifically designed to be fed directly into an AI prompt. It contains all recent job activity in a clean markdown format that any LLM can understand:

  • Read the customer's move timeline and addresses aloud before connecting to the agent
  • Pass mdThreads to your AI as conversation context
  • Use config.aiName and config.businessHours to personalize the IVR greeting
  • Use simpleInventory to summarize what the customer is moving

Response: New Job Created

When the caller's phone number doesn't match any existing customer, a new customer and lead job are created. The response includes "newJob": true.

{
  "newJob": true,
  "job": {
    "id": "abfecdc0-4d5f-11f0-af3e-039651f9f486",
    "code": "TLED-WRK-P14",
    "stage": "lead",
    "state": "open",
    "total": 0,
    "currency": "USD",
    "timeline": "2025-06-19",
    "metadata": {
      "jobOrigin": "Avoca",
      "jobType": "Residential"
    },
    "users": [
      {
        "role": "customer",
        "phone": "7035550124",
        "familyName": "Wonderland",
        "givenName": "Alice",
        "userId": "abf075e0-4d5f-11f0-af3e-039651f9f486",
        "email": null
      }
    ],
    "tags": [
      { "name": "Existing", "category": "Lead", "color": "#FF964F" }
    ]
  },
  "customer": {
    "role": "customer",
    "phone": "7035550124",
    "familyName": "Wonderland",
    "givenName": "Alice",
    "userId": "abf075e0-4d5f-11f0-af3e-039651f9f486",
    "email": null
  },
  "timezone": "America/New_York",
  "config": {
    "companyName": "You Move Me",
    "aiName": "Bee AI",
    "businessHours": "8AM to 6PM Monday to Friday and 9AM - 1PM Saturday and Sunday.",
    "aiVoice": "Polly.Joanna-Neural"
  },
  "simpleInventory": "No Inventory Set",
  "fullInventory": {
    "rooms": [],
    "specialtyItems": [],
    "totalBoxes": 0,
    "totalItems": 0,
    "totalVolume": 0,
    "totalWeight": 0
  },
  "mdThreads": "- Alice Wonderland started thread (Inbound Call): Data dip (Avoca) to +18005551212\n\n---\n\n- System: created job\n"
}

Response: Existing Job Matched

When the caller's phone number matches an existing customer, the most recent open job is returned. The response has "newJob": false (or the field is absent).

The response shape is identical to the new job response, except newJob is absent/false, and mdThreads contains the full existing call history rather than just a "created job" entry. This gives your IVR the complete context of the customer's relationship with the moving company.

Key differences when a job exists:

  • mdThreads contains all prior call records, SMS threads, estimates sent, and agent notes
  • fullInventory may contain the customer's saved inventory items
  • fields may contain custom job field values (e.g., access codes, special instructions)
  • The job's stage indicates where the customer is in the sales funnel (lead → estimate → booking → invoice)
  • A new inbound call comment is always created on the job regardless of whether it's new or existing

Complete cURL Example

#!/bin/bash

USERNAME="your@email.com"
PASSWORD="yourpassword"
ZONE="your-zone-id"

curl -X POST \
  "https://moveright.app/api/datadip/voice?zone=$ZONE" \
  -H "Authorization: Basic $USERNAME:$PASSWORD" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "call-abc-123",
    "direction": "inbound",
    "origin": "My Phone System",
    "tags": ["IVR"],
    "url": "https://myplatform.com/calls/call-abc-123",
    "note": "Inbound call from website lead",
    "called_phone_number": "+18005551212",
    "caller_name": "John Smith",
    "caller_phone_number": "+17035550123",
    "caller_country": "US",
    "caller_state": "OH",
    "caller_city": "Toledo",
    "caller_zip": "43607"
  }'

Common Use Cases

AI Agent Speed-to-Lead (e.g. Avoca)

When a new lead comes in via your AI calling agent (Avoca, etc.), POST their info to the datadip endpoint before the AI calls them back. The response gives the AI the customer's full context including move details, timeline, and prior conversations — enabling a highly personalized first call.

Custom IVR Screen Pop

Build a screen pop system that queries MoveRight when your business line rings. The response gives the agent the customer's name, job code, move date, and addresses before they even say hello. The agent sees it all on screen the moment they pick up.

After-Hours Call Capture

When your office is closed and an unknown caller rings, use the datadip endpoint to create a lead automatically and trigger MoveRight's new-lead notifications (email, push, SMS to job watchers). The caller's information is captured even when no one is available.

Multi-Location Call Routing

For franchise operations, POST to the datadip endpoint with the caller's zip code. MoveRight resolves which franchise zone serves that area and returns the correct zone's job and configuration. Use this to route the call to the right franchise location automatically.