Use cases

Text-to-buy over iMessage: answer a shopper's question, then send a payment link

ZeroSettle lets a DTC brand or small shop run text-to-buy over iMessage: a shopper texts a product question from a “Text us” link or a QR code on the packaging, and gets the answer and a Stripe Payment Link back in the same thread. The answer comes from ZeroSettle's hosted AI agent (Beta), set with a purchase goal and that link, or from your own model on the webhook. Because the shopper texts first, the link is tappable right away and the shopper never counts against the new-contact limit. Card details go only into Stripe's payment page, never into the thread.

Key takeaways

  • What it is: a “Text us” number on product pages and packaging. Answers and a Stripe Payment Link come back in the same iMessage thread, from your brand's own number.
  • Two ways to run it: the hosted AI agent (Beta) with no code, or your own model plus Stripe's checkout.session.completed webhook. Only the second can text “Paid ✅” back.
  • Main limit: shoppers text first, so the new-contact limit never applies. The hosted agent uses one AI credit per text it sends; Pro includes 1,000 a month.
  • Price: Pro is $49/month for one number. Growth, for several numbers working as one, is from $599/mo.
  • What it does not do: reach Android shoppers, take payment inside the conversation (no card numbers, no Apple Pay in the thread), or, with the hosted agent, check live stock or see whether a shopper paid.

Who uses iMessage for text-to-buy?

Text-to-buy over iMessage suits DTC brands, small shops, coffee roasters and course sellers with a short, well-defined product list, where the last question before buying fits in one text. 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 problem is the shopper with one question who leaves the product page to find the answer. A live-chat window closes with the tab; a text thread stays in Messages, link included. It suits a big catalog or a mostly Android audience less well (see when ZeroSettle is not a fit). After the sale, the same number can answer “where is my order?” texts, and creators run this flow from a “text me” line. More jobs are on the use-case hub.

How iMessage for text-to-buy works, step by step

The shopper starts the thread, the hosted agent or your model sends a Stripe Payment Link, and Stripe tells your server when the shopper has paid.

  1. Add a “Text us” link to each product page with the product prefilled, such as sms:+15555550142&body=Question%20about%20the%2012oz%20Decaf, and print a QR code of it on bags or menus (how to build sms: links and QR codes).
  2. The shopper texts first, so your number is a known sender: links are tappable, and the shopper is never a new contact.
  3. Without code: switch the line group to Managed by AI Agent (Beta), list products, prices and allowed discounts in the business_context, and set goal to purchase with your Payment Link.
  4. With a developer: keep the line Managed by API. ZeroSettle posts each text to your webhook as message.received about 1–2 seconds after it lands. Your model answers through POST /api/imessage/send and, when it detects purchase intent, sends the link with a per-shopper client_reference_id.
  5. The shopper pays on Stripe's hosted page, and Stripe sends checkout.session.completed to your server.
  6. Your handler texts “Paid ✅” and adds a 👍 tapback with POST /api/imessage/reactions. This needs Managed by API: a line the hosted agent manages refuses your sends.

Example conversation: text-to-buy

This is the developer route, from question to confirmation.

  1. Today 8:12 AM
  2. Customer: does the 12oz bag come in decaf?
  3. Business: It does! Swiss Water decaf, same roast. $18 a bag, or $15 on a subscription.
  4. Customer: one bag pls👍
  5. Business: Here you go: buy.stripe.com/… Ships tomorrow.
  6. Customer: done
  7. Business: Paid ✅ Tracking comes tomorrow morning.
Illustrative example with a fictional roaster, Ridge Coffee. Blue bubbles are sent from Ridge Coffee's number; gray bubbles are the shopper's. “Paid ✅” and the 👍 followed Stripe's checkout.session.completed, not the shopper's “done”. With the hosted agent, nothing in the thread would confirm the payment, because the agent can't see Stripe.

Setup: the hosted agent with goal purchase, or your model plus Stripe webhooks

Pick one route per line group, because the two don't mix: on a group the agent manages, your API sends, MCP send_imessage and the console composer are refused with 403 managed_by_zerosettle.

Two ways to run text-to-buy on ZeroSettle (API docs, checked October 12, 2026)
QuestionHosted AI agent (Beta)Your model (Managed by API)
What it knowsYour business_context and the threadWhatever your code looks up, such as stock
Payment linkOne link for the purchase goalPer shopper, with a client_reference_id
“Paid ✅” in the threadNoYes
Cost per text1 AI creditNo AI credits

No code: the hosted agent with a purchase goal

Set the agent in the console's Messaging tab or with one call. It answers everything a shopper sent since its last text in one go, as up to three texts with the typing bubble first, or sends nothing. In the docs' words, it “never invents facts your business context doesn't give, says it is your automated assistant if sincerely asked, and points anyone who wants no more texts to STOP.” Writing “No other discounts” gives it the answer to a discount request.

bash
BASE=https://portal.zerosettle.io
curl -s -X PUT "$BASE/api/imessage/agent" \
  -H "Authorization: Bearer $ZEROSETTLE_TOKEN" -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{"managed_by": "zerosettle", "goal": "purchase", "link": "https://buy.stripe.com/your_link",
 "triggers": [],
 "business_context": "You answer texts for Ridge Coffee. 12oz bags, House Roast or Swiss Water Decaf (same roast): $18, or $15 a bag on a subscription. No other discounts. Orders by 2 PM Pacific ship the next business day. Never ask for card numbers. You can't see payments: if they say they paid, thank them and say the confirmation comes by email. Anything else: hello@ridgecoffee.example."}
JSON

The business_context takes up to 40,000 characters. first_message (1–3 texts) goes out only when the agent starts a conversation, so text-to-buy can ignore it. The agent can't see Stripe, so the context tells it never to confirm a payment, and its triggers are off ([]): the default follow-up goes the morning after the last message and would nudge shoppers who already paid. No teammate can answer in the console while the agent manages the line, hence the email. personality and response_time are covered in the hosted AI agent explainer.

With a developer: your model, then Stripe's webhook

Your ZeroSettle webhook receiver hands each message.received to your model, as in the AI agent docs, and the model calls send_link as a tool when the shopper asks to buy. A second endpoint takes Stripe's event.

python
# checkout.py: run with  uvicorn checkout:app --port 8200
import os, secrets, time, requests, stripe
from fastapi import BackgroundTasks, FastAPI, Request, Response

BASE = "https://portal.zerosettle.io"
ZS = {"Authorization": f"Bearer {os.environ['ZEROSETTLE_TOKEN']}"}
LINK = "https://buy.stripe.com/your_link"
ORDERS: dict[str, dict] = {}                     # ref -> order; keep these in your database
app = FastAPI()

def zs(path: str, body: dict) -> None:
    for _ in range(5):                           # one send at a time per line: retry line_busy
        r = requests.post(f"{BASE}/api/imessage/{path}", headers=ZS, json=body, timeout=90)
        if r.status_code != 429 or r.json()["error"]["code"] != "line_busy":
            return
        time.sleep(2)

def send_link(handle: str, message_id: int) -> None:   # the model's tool; message_id = "one bag pls"
    ref = "rc_" + secrets.token_hex(8)
    ORDERS[ref] = {"handle": handle, "message_id": message_id, "session": None}
    zs("send", {"to": handle, "text": f"Here you go: {LINK}?client_reference_id={ref} Ships tomorrow."})

def claim_order(ref, session_id: str):           # None if unknown or confirmed already
    order = ORDERS.get(ref or "")
    if order is None or order["session"]:
        return None
    order["session"] = session_id
    return order

def confirm(order: dict) -> None:
    zs("send", {"to": order["handle"], "text": "Paid ✅ Tracking comes tomorrow morning."})
    zs("reactions", {"message_id": order["message_id"], "reaction": "like"})

@app.post("/stripe")
async def stripe_webhook(request: Request, tasks: BackgroundTasks):
    try:
        event = stripe.Webhook.construct_event(await request.body(),
            request.headers.get("Stripe-Signature", ""), os.environ["STRIPE_WEBHOOK_SECRET"])
    except Exception:
        return Response(status_code=400)
    s = event["data"]["object"]
    if event["type"] in ("checkout.session.completed", "checkout.session.async_payment_succeeded") \
            and s["payment_status"] != "unpaid":
        order = claim_order(s["client_reference_id"], s["id"])
        if order:
            tasks.add_task(confirm, order)       # answer Stripe first, text after
    return Response(status_code=200)

Stripe's client_reference_id takes up to 200 letters, digits, dashes or underscores. Stripe silently drops a value with anything else in it (a phone number's +, for one) and says to keep sensitive information out of it, hence the opaque reference. Stripe also warns that fulfillment can run more than once for the same Checkout Session, so claim_order confirms each order once. like is the 👍; the other tapbacks are love, dislike, laugh, emphasize and question. See the docs on sending and webhooks.

Limits and consent for text-to-buy

Text-to-buy is shopper-initiated, so ZeroSettle's new-contact limits never apply. As the docs put it, “Anyone who texted the line first is never limited, and neither is an ongoing conversation.” What can still bite is AI credits, if the hosted agent answers, and, on every plan, the cap on unanswered texts to one shopper.

ZeroSettle limits as they apply to text-to-buy (API docs, checked October 12, 2026)
LimitProGrowth
New contacts a day, per number5; shoppers who text first don't count50; same
Unanswered texts to one shopper2 until they reply; texts within 5 minutes of the first count as one
Messages in and outUnlimitedUnlimited
AI credits (hosted agent), per account1,000 a month5,000 a month
Sends from one lineOne at a time, normally 2–5 sSame

The limit math for shopper questions

  • Credits: the example costs the hosted agent 2 AI credits up to the link. 300 shoppers a month at 4 agent texts each is 1,200 credits: Pro's 1,000 plus a $50 pack of 1,000, leaving 800 that never expire. At zero the agent goes quiet; texts still reach the inbox.
  • A launch burst: 40 shoppers in one minute, two replies each, is 80 sends at 2–5 seconds apiece from one line, so the last answer can wait 3 to 7 minutes for sending alone. zs() above retries 429 line_busy after 2 seconds.
  • The unanswered rule: if a shopper pays without texting back, the link and “Paid ✅” count as two unanswered texts when they go out more than 5 minutes apart. A next-day tracking text would be the third, and ZeroSettle refuses it with 403 awaiting_reply on every plan, so send tracking by email there.

Consent in a text-to-buy thread

The shopper texted about a product, so keep the thread to that question and the order. A purchase is not a sign-up for marketing texts.

A text with the word STOP in it opts the shopper out on every number on your account, even “how do I stop my subscription?”. Your texts and tapbacks to them then return 403 recipient_opted_out until they text START, so put subscription pause and cancel steps on your site and answer that question by email. This isn't legal advice; have counsel review your consent flow.

When ZeroSettle is not a fit for text-to-buy

ZeroSettle is the wrong tool for text-to-buy when the chat itself would have to take the payment, or when shoppers can't receive iMessage.

  • You'd capture card details in the chat. Never; Stripe's hosted page takes the card.
  • A large catalog needs live stock lookups, and you have no developer. The hosted agent knows only its business context and can't look anything up. Your own model on the webhook can.
  • Many shoppers are on Android. There is no SMS fallback (it is on ZeroSettle's roadmap), and the sms: link opens the SMS app, so keep email or chat beside it.
  • You want Apple Pay inside the conversation. Apple lists “making payments using Apple Pay” as part of Apple Messages for Business, which ZeroSettle is not; see Apple Messages for Business vs an iMessage number.

To reach opted-in shoppers who haven't texted you, abandoned checkout follow-up is the outbound counterpart.

How much does iMessage for text-to-buy cost?

Text-to-buy costs the ZeroSettle plan price, plus an AI credit pack only if the hosted agent sends more texts than the plan includes. There is no per-message fee; Stripe's processing fees are separate.

ZeroSettle plans for text-to-buy (zerosettle.io and API docs, checked October 12, 2026)
PlanPriceIncludes
Pro$49/monthOne number, 5 new contacts a day, unlimited messages with people who message you first, 1,000 AI credits a month, no setup fee, 30-day money-back guarantee
GrowthFrom $599/moSeveral numbers working as one, 5,000 AI credits a month
AI credit packs1,000 for $50; 5,000 for $200Paid once, never expire

See ZeroSettle pricing, or get started on Pro.

Frequently asked questions

Can shoppers pay with Apple Pay?

Yes, on Stripe's page rather than in the thread: Stripe says Apple Pay works on Payment Links with no additional configuration.

Can I use a checkout link other than Stripe's?

Yes. The hosted agent's link can be any https:// link, and your code can send any URL. Only the “Paid ✅” step needs your checkout to notify your server, as Stripe's webhook does here.

What if a shopper texts a card number anyway?

Don't use it; reply with the link. ZeroSettle keeps messages indefinitely for now, so delete that shopper's stored thread with DELETE /api/imessage/conversations/{handle}, and clear it from your own webhook logs. Nothing already delivered is unsent.

Can I text shoppers later about new products?

Only with separate marketing consent: in the US, prior express written consent, which the FCC's rule says can't be a condition of purchase. Send nothing promotional before 8 am or after 9 pm in their time zone. See iMessage marketing and TCPA consent. This isn't legal advice; ask counsel.

Sources

  1. ZeroSettle iMessage API docs: “Send a message” (links, reactions), “Read messages”, “Customer support” (sms: links), “AI agent”, “Webhooks, step by step” and “Errors, limits, and compliance”. Checked October 12, 2026.
  2. Track a payment link (the client_reference_id URL parameter), Stripe Docs. Checked October 8, 2026.
  3. Fulfill orders (Payment Links use Checkout; checkout.session.completed, checkout.session.async_payment_succeeded, payment_status, fulfilling once per session), Stripe Docs. Checked October 8, 2026.
  4. Accept payments online without writing code (Payment Links: a Stripe-hosted page, reusable with many customers), Stripe Docs. Checked October 8, 2026.
  5. Apple Pay (“For Payment Links or hosted Checkout, Apple Pay works with no additional configuration”), Stripe Docs. Checked October 8, 2026.
  6. Apple Messages for Business & Privacy (“making payments using Apple Pay”), Apple. Checked October 8, 2026.
  7. 47 CFR § 64.1200, Delivery restrictions, paragraph (f)(9), the FCC's TCPA rule (Legal Information Institute, Cornell Law School). Checked October 8, 2026.

Written by the ZeroSettle team. 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.

Product facts on this page come from the ZeroSettle iMessage API docs and zerosettle.io as of October 12, 2026. Stripe, Apple and FCC details come from the pages listed under Sources, checked October 8, 2026. This page is not legal advice.

Text your customers from your own iMessage number

ZeroSettle gives your business its own phone number on real iMessage, running on Apple hardware we operate for you in a server facility. Your code sends with one API call and hears every reply on a signed webhook.

Pro is $49 a month with a 30-day money-back guarantee. Growth, for several numbers working as one, is from $599/mo.