iMessage for car dealership leads: lot photos and voice walkarounds
ZeroSettle lets a car dealership answer an internet lead on iMessage seconds after it arrives: a link-free question about that exact vehicle first, then lot photos, a 30-second voice walkaround that plays as Messages' native voice bubble, and the test-drive link once the shopper replies. With a number per salesperson, each can text with their own name and photo. Plan around pacing: Pro opens 5 new conversations a day per number, and Growth 50 a day with at most 3 per 15 minutes per number, so a Saturday burst of leads is spread across numbers or waits its turn.
Key takeaways
- What it is: ZeroSettle is an iMessage API: a real phone number on real iMessage, running on Apple hardware we operate for you, that your code texts customers from and hears back on through a bearer token and signed webhooks.
- The dealership flow: one link-free question per lead; after the reply, captioned lot photos (up to 5 MB each), a voice walkaround (up to 6 MB) and the test-drive link.
- Price: Pro is $49/month, starting with one number. Growth, for several numbers working as one, is from $599/mo.
- Main limit: new contacts per number: Pro 5 a day; Growth 50 a day and 3 per 15 minutes. Shoppers who text first never count.
- What it does not do: no SMS fallback for Android shoppers, no video in either direction, and no native DMS integration (built-in CRM support is limited; Close is supported).
Who uses iMessage for dealership leads?
iMessage lead follow-up fits franchise and independent dealers whose BDC, internet sales manager or salespeople answer web leads that include a mobile number and consent to texts. Shoppers often ask several dealers at once, so the first real conversation matters, and a text that names the exact car and asks one question is easier to answer than a template email or a call from an unknown number.
It is not for aged leads who never opted in, and it can't reach Android shoppers (see when ZeroSettle is not a fit). The same pattern for listings is in real estate lead follow-up over iMessage; more workflows are in 50 ways businesses use iMessage.
How iMessage for dealership leads works, step by step
Your CRM's new-lead event triggers one text, and the photos, voice walkaround and link wait for the shopper's reply. ZeroSettle carries the messages; lead assignment stays in your CRM.
- A lead arrives with a mobile number and consent to texts. ZeroSettle checks whether the number is on iMessage before the first message and sends nothing if it isn't (
422 not_on_imessage); then use your CRM's SMS or email. - Your code calls
POST https://portal.zerosettle.io/api/imessage/sendwith a link-free question about that exact vehicle. With several numbers, name the assigned salesperson'sline_id; with each salesperson's number in its own line group, the shopper sees that salesperson's name and photo. The call returns once the line hands the message to Apple, normally in 2–5 seconds. No link yet: in a first message to someone who has never texted the number, a link shows as plain text until the shopper replies. - The reply reaches your webhook as a signed
message.receivedevent about 1–2 seconds after the line receives it, naming itsline_idon a multi-number account, so it goes to the salesperson who owns that number. - The salesperson sends lot photos (
image_b64, up to 5 MB each, caption in the same bubble), a voice walkaround (audio_b64in m4a, mp3 or another common format, up to 6 MB, arriving as a native voice bubble) and the now-tappable test-drive link. The ZeroSettle console sends texts and photos; voice goes through the API. - The shopper texts trade-in photos one per text: a message with several photos delivers only the first, and a video arrives with no file.
Follow the voice walkaround with a one-line text recap of its key facts (miles, price). A voice bubble carries no caption, and Apple's iPhone User Guide says a recipient must tap Keep within 2 minutes after listening to save an audio message, unless they set audio messages never to expire.
Example conversation: a dealership lead
The order keeps every link tappable: a question first, media after the reply, the link last.
- Thu 6:12 PM
- Dealership: Hi Marcus, it's Jen at Alder Creek Auto. The blue 2024 RAV4 XLE you asked about is on the lot right now. Want me to send a few real photos?
- Shopper: yeah please. also have a 2019 civic to trade
- Dealership: Photo: the RAV4 on the lot
- Dealership: Photo: the interior
Here it is, no filters. - Dealership: Voice message, 0:30
- Dealership: Recap: 21k miles, one owner, $31,400.
- Dealership: Send me a pic of the Civic and the odometer and I'll get you a trade range today.
- Shopper: Photo: the Civic
- Shopper: 68k miles
- Dealership: Thanks! Range is $14,500–$15,800. Test drive Saturday? example.com/drive
Jen's opening names her, the dealership and the car, which follows ZeroSettle's consent guidance that your first message says who you are.
Setup: a CRM lead trigger plus media sends
Two pieces cover the flow: a send helper your CRM calls, and the docs' webhook receiver with one change, routing by line (see the send docs and webhook steps).
# dealer_leads.py: the send side, called from your CRM
import base64, os
import requests
BASE = "https://portal.zerosettle.io"
AUTH = {"Authorization": f"Bearer {os.environ['ZEROSETTLE_TOKEN']}"}
def send(to: str, line_id: str | None, **fields) -> dict:
r = requests.post(f"{BASE}/api/imessage/send", headers=AUTH, timeout=120,
json={"to": to, "line_id": line_id, **fields}) # None: ZeroSettle picks
return r.json() # on error.code "new_contact_limit", queue a retry after error.retry_after_s
def b64(path: str) -> str:
with open(path, "rb") as f:
return base64.b64encode(f.read()).decode()
def on_new_lead(lead: dict) -> dict: # your CRM's new-lead hook
if not lead["text_consent"]:
return {"skipped": "no consent to texts"}
return send(lead["mobile"], lead.get("rep_line_id"),
text=f"Hi {lead['first_name']}, it's {lead['rep']} at Alder Creek Auto. The {lead['vehicle']} "
"you asked about is on the lot right now. Want me to send a few real photos?")
def send_walkaround(to, line_id, photos: list[str], caption: str, voice: str, recap: str, link: str) -> None:
for path in photos[:-1]: # only after the shopper replies
send(to, line_id, image_b64=b64(path))
send(to, line_id, image_b64=b64(photos[-1]), text=caption) # caption shares the bubble
send(to, line_id, audio_b64=b64(voice), audio_format=voice.rsplit(".", 1)[-1])
send(to, line_id, text=recap) # a voice bubble has no caption
send(to, line_id, text=f"Test drive this week? Pick a time: {link}")
For replies, start from the docs' complete receiver. It checks X-ZeroSettle-Signature (HMAC-SHA256 over "<t>." plus the raw body, compared in constant time) and dedupes retries. Replace its auto-reply with this router, run in the background, because ZeroSettle expects a 2xx within 10 seconds:
# dealer_leads.py, continued: called for each message.received
def route(m: dict) -> None:
rep = rep_for_line(m.get("line_id")) # your table: line_id -> salesperson
if m.get("kind") == "image" and m.get("image"): # a trade-in photo
m["photo"] = requests.get(BASE + m["image"]["url"], headers=AUTH, timeout=60).content
notify(rep, m) # CRM note + alert to the salesperson
On a single-number account, leave line_id out: null keeps the automatic choice, so the code runs on both plans. To log messages on the lead, see logging iMessages in your CRM; formats are in what an iMessage API can send.
Limits and consent for dealership leads
Each number can open only so many new conversations per 15 minutes and per day; replies and ongoing threads are never limited. Shoppers who text first, from a window-sticker QR code or a text button on the vehicle page, never count and skip iPhone's unknown-sender filter (see getting customers to text first).
| Limit | Pro | Growth |
|---|---|---|
| New contacts per day (3 AM to 3 AM Eastern) | 5 | 50 |
| New contacts per rolling 15 minutes | — | 3 |
| Unanswered messages to one shopper | 2, then 403 awaiting_reply | 2, then 403 awaiting_reply |
| Replies and ongoing conversations | Not limited | Not limited |
Source: ZeroSettle iMessage API docs, “Errors, limits, and compliance”. A new contact is a handle the line delivers a text, voice message or photo to first.
The limit math for a Saturday-morning burst
Take 12 new leads that land at 10 AM on a Saturday from shoppers who have never texted you.
| Setup | Sent right away | The rest |
|---|---|---|
| Pro, one number | 5 | 7 get 429 new_contact_limit and wait for the 3 AM Eastern reset; resend after retry_after_s |
| Growth, every lead named to one line | 3 | 3 more every 15 minutes; the last around 10:45 |
| Growth, spread over three numbers | 9 | 3 wait about 15 minutes |
| Growth, spread over four or more numbers | 12 | None, if no number gets more than 3 |
A send that names a full line is refused without trying your others, so assign leads round-robin, or leave line_id out and ZeroSettle picks the line with the most room left today; the response's record.line_id tells your CRM which salesperson owns the lead. On Pro, the 6th new lead of the day on a number waits for the 3 AM Eastern reset. On every plan, a shopper who hasn't answered can get your question and one follow-up, then sends return 403 awaiting_reply (messages within 5 minutes of the first count as one). The limits help keep the number out of Apple's spam filters.
Consent comes first
Text only leads whose form carried clear consent to texts, and ask third-party providers to pass the consent record along. Don't text aged leads or past customers who never opted in. ZeroSettle suspends lines used for unsolicited messaging, and its docs note US TCPA damages of $500 to $1,500 per message and that marketing texts need written consent. The FCC's TCPA rule defines prior express written consent as a signed agreement (an electronic signature counts) that clearly authorizes the seller to send ads or telemarketing messages to a named phone number, and that tells the shopper signing isn't a condition of buying. This isn't legal advice; check your forms with counsel.
Nothing promotional before 8 am or after 9 pm in the shopper's time zone, so hold an 11 pm lead's first text until morning. A text with the word STOP in it, or a clear request like “take me off your list”, sent to any salesperson's number, blocks the shopper on every number on the account. More in the TCPA consent guide.
When ZeroSettle is not a fit for dealership leads
ZeroSettle is the wrong tool for dealership leads in these cases:
- You'd text aged leads or past customers who never opted in. That is unsolicited messaging.
- You must reach Android shoppers. There is no SMS fallback, and iMessage goes only to iPhones and other Apple products; Messages uses RCS or SMS for other phones, as Apple explains. Keep your CRM's SMS for them.
- You want video walkarounds. Video isn't supported. Use a voice message and photos.
- You need a native DMS integration. There is none, and built-in CRM support is limited (Close is supported); for anything else you build the webhook relay.
How much does iMessage for dealership leads cost?
When your own code sends the texts, lead follow-up costs the plan price: messages are unlimited (counted), with no per-message fee. Only the hosted AI agent uses AI credits, one per text it sends; Pro includes 1,000 a month and Growth 5,000.
| Plan | Price | Fits |
|---|---|---|
| Pro | $49/month | One number to start, 5 new contacts a day per number, unlimited messages with people who message you first, self-serve, no setup fee |
| Growth | From $599/mo | 3+ numbers working as one, a name and photo per line group, 50 new contacts a day per number, after a demo |
Both plans come with a 30-day money-back guarantee on the subscription. See ZeroSettle pricing, get a number, or read the API docs.
Frequently asked questions
What happens when a lead moves to another salesperson?
On a multi-number account, the shopper keeps hearing from the number their conversation is on. Naming the new salesperson's line_id starts a separate thread from a different number, which counts as a new contact for that line, so for a handoff keep sending from the original line and reassign the lead in your CRM.
Does “I'll stop by Saturday” count as an opt-out?
Yes. ZeroSettle treats a text with the word STOP in it as an opt-out, and sends to that shopper from any of your numbers return 403 recipient_opted_out. Their messages still reach your webhook, so the salesperson can confirm the visit by phone or email; texting resumes when the shopper texts START, or ZeroSettle can clear the opt-out if the shopper asks you another way.
Can the hosted AI agent answer leads instead of a salesperson?
Yes, in Beta: on a line group set to Managed by AI Agent, you start each lead with POST /api/imessage/agent/start and the agent answers every inbound text from your business context, at one AI credit per text it sends. Your own sends on that group's lines are refused (403 managed_by_zerosettle), so photo and voice walkarounds need a group managed by API.
Sources
- ZeroSettle iMessage API docs: “Your iMessage number” (more than one number), “Send a message”, “Attachments”, “AI agent”, “Webhooks, step by step” and “Errors, limits, and compliance”. Checked October 8, 2026.
- ZeroSettle homepage: plans and prices. Checked October 8, 2026.
- Send and receive audio messages in Messages on iPhone, iPhone User Guide, Apple Support. Checked October 8, 2026.
- Screen and filter text messages on iPhone, iPhone User Guide, Apple Support. Checked October 8, 2026.
- What is the difference between iMessage, RCS, and SMS/MMS?, Apple Support. Checked October 8, 2026.
- 47 CFR § 64.1200, Delivery restrictions, paragraph (f)(9) (the definition of prior express written consent), the FCC's TCPA rule (Legal Information Institute, Cornell Law School). Checked October 8, 2026.