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 Searches for an existing customer by caller phone number
- 2 If found, pulls the most recent open job for that customer
- 3 If not found, creates a new customer and lead job automatically
- 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 Creates an inbound call comment on the job for tracking
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
mdThreadsto your AI as conversation context - Use
config.aiNameandconfig.businessHoursto personalize the IVR greeting - Use
simpleInventoryto 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:
mdThreadscontains all prior call records, SMS threads, estimates sent, and agent notesfullInventorymay contain the customer's saved inventory itemsfieldsmay contain custom job field values (e.g., access codes, special instructions)- The job's
stageindicates 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.