iBlueText API
Base URL https://ibluetext.com/api/v1 · JSON over HTTPS.
Introduction
The iBlueText API lets you validate which numbers are on iMessage and send real blue-bubble messages from your dedicated line — straight from your own app, backend, or CRM. Every request is authenticated with an API key and returns JSON.
Which API for what
All endpoints share the same base URL and Bearer-key auth — they're grouped here by purpose so you pick the right one. Full details for each are in the sections below.
| Purpose | Endpoint |
|---|---|
| iPhone Lookup — is a number on iMessage? | POST/GET /api/v1/lookup |
| Send — send an iMessage/SMS | POST/GET /api/v1/send |
| SMS Verify / 2FA — send & check a code | POST /api/v1/verify · /siteverify · /sites |
| Conversations — read full in/out message history (for CRMs / agents) | GET /api/v1/conversations |
| Verified contacts — export widget-verified numbers | GET /api/v1/contacts |
| Balance & usage — credits + per-line daily caps | GET /api/v1/balance |
Get a key under Integrations → API keys. Every request uses Authorization: Bearer <key> and only ever sees your own account's data.
For AI agents 🤖
iBlueText is built to be set up by an AI agent. A human verifies once (the only human step), then your agent does the rest via the API. There's a machine-readable summary at ibluetext.com/llms.txt.
Paste this to your agent (Claude or any) to get started:
I'm setting up iBlueText (https://ibluetext.com) for SMS/iMessage.
Read https://ibluetext.com/llms.txt and https://ibluetext.com/docs/.
I'll verify I'm human via SMS and give you my API key
(send it as: Authorization: Bearer <key>). Then:
1) create a verify-widget site (POST /api/v1/sites) and give me the embed snippet,
2) help me run an iPhone lookup (POST /api/v1/lookup) on my list,
3) set up sending (POST /api/v1/send) as I describe.
Your agent can create widget sites, run lookups, send messages, and pull contacts entirely through the API — see the endpoints below.
Authentication
Create a key under Settings → API keys, then send it as a Bearer token on every request. Keep keys secret — anyone with a key can spend your credits.
Authorization: Bearer ibt_live_xxxxxxxxxxxxxxxxxxxxxxxx
Quickstart
Check whether three numbers are on iMessage:
curl https://ibluetext.com/api/v1/lookup \
-H "Authorization: Bearer $IBT_KEY" \
-H "Content-Type: application/json" \
-d '{"numbers": ["+18135550142", "+17275550199", "+13055550123"]}'
{ "id": 8412, "status": "queued", "total": 3,
"poll_url": "https://ibluetext.com/api/v1/lookup?id=8412" }
Then poll the poll_url until status is done.
POST/lookup
Submit numbers to validate. Numbers are de-duplicated and must include a country code. One lookup credit is spent per number (your first 100 are free).
Body
{ "numbers": ["+18135550142", "+17275550199"] } // array, or comma-separated string
Response 201
{ "id": 8412, "status": "queued", "total": 2, "poll_url": "…/lookup?id=8412" }
GET/lookup?id=<id>
Fetch job progress and results. imessage is true (blue bubble), false (SMS), or null (not yet checked).
{ "id": 8412, "status": "done", "total": 2, "completed": 2, "iphones": 1,
"results": [
{ "number": "+18135550142", "imessage": true, "checked": true },
{ "number": "+17275550199", "imessage": false, "checked": true }
] }
POST/send
Queue an iMessage from your active sending line. Requires a provisioned line. Recipients who replied STOP are blocked automatically.
Body
{ "to": "+18135550142",
"body": "Hi {firstname}! Your order shipped 🎉",
"first_name": "Sarah", // optional — fills {firstname}
"line_id": 12 } // optional — defaults to your first active line
Response 201
{ "id": 99213, "to": "+18135550142", "status": "queued", "poll_url": "…/send?id=99213" }
GET/send?id=<id>
{ "id": 99213, "to": "+18135550142", "channel": "imessage", "status": "delivered", "sent_at": "2026-06-17 14:02:11" }
Status values: queued → sent → delivered, or failed.
SMS Verify — widget & API
Add "verify you're human via SMS" to any form. Two ways:
Drop-in widget (easiest)
Create a site under SMS Verify to get a site_key, then paste this above your form's submit button:
<div class="ibt-verify" data-sitekey="ibt_site_xxx" data-theme="auto"></div>
<script src="https://ibluetext.com/v.js" async></script>
The widget gates your submit button until verified, then injects a hidden ibt_token field. Themes: auto / light / dark. It also emits an ibt-verified DOM event.
Where to place it: any form that collects a phone (signup, contact, checkout); the "add your phone" step after a Google/Apple login (social login gives you an email but no verified phone); or as a gatekeeper — render it on a page and only grant access (or call your backend) once the ibt-verified event fires or /siteverify confirms the token.
Capturing name & email: the widget auto-reads the name + email from the surrounding form and attaches them to the verified contact (so a contact form becomes name+email+verified-phone). Add data-require="name,email" to require those fields before the user can verify, or data-name-field/data-email-field (CSS selectors) to target specific inputs. Omit for phone-only capture.
Exactly where in the page:
- Inside a form (contact, signup, lead) → put the widget div inside the
<form>…</form>tags, after the name/email inputs and just before the submit button. It auto-finds its parent<form>, gates that form's submit button, and reads the name/email from it. Example (BCI contact form): place it after Email, before Subject. - Standalone / gatekeeper (outside any form) → if it's not inside a
<form>, it verifies phone only (nothing to gate or capture). Listen for theibt-verifiedevent to unlock the page/content.
For one-tap autofill (recommended): add autocomplete tokens to your own fields — name field autocomplete="name", email field type="email" autocomplete="email". The widget's phone input already has autocomplete="tel". With all three, iOS "AutoFill Contact" fills name + email + phone in one tap, and the verification code one-tap-fills on iPhone / auto-fills zero-tap on Android Chrome. The code field needs nothing extra — the widget handles it.
REST API (server-side)
# 1. start — send a code (server uses your secret API key)
curl https://ibluetext.com/api/v1/verify \
-H "Authorization: Bearer $IBT_KEY" -H "Content-Type: application/json" \
-d '{"phone":"+18135550142","page_url":"https://you.com/signup"}'
# -> { "id": 5512, "status": "queued" }
# 2. check — confirm the code the user typed
curl "https://ibluetext.com/api/v1/verify?action=check" \
-H "Authorization: Bearer $IBT_KEY" -H "Content-Type: application/json" \
-d '{"id":5512,"code":"481920"}'
# -> { "verified": true, "token": "…", "phone": "+18135550142", "channel": "imessage" }
The code is delivered by iMessage (iPhone) or SMS (Android) automatically. Each verification logs a proof-of-consent record (number, time, IP, page, consent text).
POST/siteverify
Confirm a widget token on your backend with your secret key (like Cloudflare's siteverify). Tokens are single-use.
curl https://ibluetext.com/api/v1/siteverify \
-H "Content-Type: application/json" \
-d '{"secret":"ibt_secret_xxx","token":""}'
# -> { "success": true, "phone": "+18135550142", "channel": "imessage", "verified_at": "…" }
GET/contacts
Pull your verified contacts — phone, name, email, channel, and verified time — to sync into your own database or CRM. Paginate with next_since.
curl "https://ibluetext.com/api/v1/contacts?since=0&limit=200" \
-H "Authorization: Bearer $IBT_KEY"
# -> { "contacts":[ { "id":91, "phone":"+18135550142", "name":"Sarah Lee",
# "email":"sarah@x.com", "channel":"imessage", "verified_at":"…" } ],
# "count":1, "next_since":91 }
You can also download everything as CSV from SMS Verify → Download contacts.
Billing & the 402 "out of credits" error
The first 100 credits are free for testing. 1 credit = $0.005, spent by either one iPhone lookup or one SMS verification (shared pool). Separately, your first 10 SMS verifications are free (no card) — a distinct trial bucket from the 100 lookup credits. Sending iMessage/SMS instead needs an active line subscription ($99/mo + $249 setup), not credits.
When you run out, the paid endpoints return HTTP 402 with a machine-readable body so an AI agent knows exactly what to do:
{ "error": "payment_required",
"reason": "insufficient_credits", // or "subscription_required"
"message": "…buy credits to continue.",
"action": "lookup", // or "verify" / "send"
"needed": 250, "available": 0, "unit_price_usd": 0.005,
"human_action_required": true, // a HUMAN must pay — agents can't enter a card
"buy_url": "https://ibluetext.com/portal/billing.php" }
Agents: on a 402, stop and tell your human to pay at buy_url, then resume. Buy credits · Subscribe a sending line.
Check your wallet + per-line daily usage anytime: GET /api/v1/balance → credits, free-trial + free-daily lookups remaining, and each line's new-contact / non-replier counts. Poll it to warn before $0 or a daily cap.
Sending limits
To keep your number safe from carrier/Apple bans, each line is capped per customer-local day (resets 4am your time):
- 50 new iMessage + 50 new SMS first-contacts/day/line (just 15/day each during a line's first 5 days — warm-up).
- 150/channel/day total to numbers that haven't replied yet.
- Unlimited 2-way — once someone replies (and hasn't sent STOP), message them as much as you like.
- Over-cap sends hold and auto-resume the next day (drip). More lines = higher daily ceiling.
- STOP / unsubscribe auto-suppresses that number for your account, permanently.
Webhooks
Get replies and delivery events pushed to your server in real time. Set a webhook URL under Settings (coming online with your line). Example payload:
{ "event": "message.reply",
"from": "+18135550142",
"body": "Yes please!",
"received_at": "2026-06-17 14:05:00" }
Opt-outs
Compliance is automatic. Any reply containing STOP, UNSUBSCRIBE, CANCEL, QUIT, or END adds that number to your opt-out list, and the API will refuse to send to it (409). This is required under the TCPA — see our Terms.
Conversations API
Pull full two-way transcripts so your own app or AI agent can read what each contact said and act on it (e.g. update a CRM, or add/remove a listing on another site). iBlueText returns the raw in/out messages — your side does the judging.
GET/api/v1/conversations
Query params: phone (one conversation), since (ISO time — only conversations with newer activity, for incremental polling), limit (default 200, max 1000), include_no_reply=1 (also include contacts who never replied; default is repliers only).
curl "https://ibluetext.com/api/v1/conversations?limit=200" \
-H "Authorization: Bearer $IBT_KEY"
{
"count": 1,
"conversations": [
{
"phone": "+18139188356",
"company_name": "FinSanity Fishing Charters",
"link": "https://beercanisland.com/c/0XCtDU1a",
"fields": { "company_name": "FinSanity Fishing Charters", "link": "https://beercanisland.com/c/0XCtDU1a" },
"opted_out": false,
"last_activity": "2026-07-11 19:39:04",
"messages": [
{ "dir": "out", "body": "Hi is this FinSanity Fishing Charters?", "at": "2026-07-11 19:35:00", "channel": "sms", "status": "sent" },
{ "dir": "in", "body": "Yes, it is", "at": "2026-07-11 19:37:17" },
{ "dir": "out", "body": "Here's your link: https://beercanisland.com/c/0XCtDU1a", "at": "2026-07-11 19:39:40", "channel": "sms", "status": "sent" }
]
}
]
}
Each conversation carries the contact's uploaded fields (including company_name and link), an opted_out flag, and the ordered messages (dir is in or out). Generate a key under Integrations → API keys.
AI auto-replies
Turn on Inbound AI and your line answers incoming texts automatically — trained on your business, and optionally on per-contact data you provide. Two modes:
- General — answers from your business info (hours, pricing, FAQs, booking). Set it up on the AI Replies page: a business name, instructions, and a knowledge base (paste it, upload a
.txt, or auto-build from your website). - Account-specific — answers questions about the individual texting in, using data attached to their phone number. Upload a CSV with your campaign and every column becomes part of that contact's record.
Give the AI a per-contact database
When you send a campaign, include a CSV with a phone column plus any fields you want. Each row is stored against that number and handed to the AI when the person replies:
company,phone,loan_amount,rate,due_date,link
Reel Deal LLC,+18135550142,$45000,6.9%,Aug 1,https://you.com/portal/abc123
Salty Dog LLC,+17275550199,$12000,8.4%,Sep 15,https://you.com/portal/def456
Now if +18135550142 texts "what's my rate and my link?", the AI replies with 6.9% and that contact's link. Guide it from your Instructions, e.g. "If a client asks about their loan, share the amount, rate, and due date from their info; if you don't have a detail, say a teammate will follow up."
Safety: replies never cross contacts
Every reply is scoped to the exact E.164 phone number that texted in — the model only ever receives that one contact's fields, so John can't get Jane's data. The AI is also instructed never to invent account details (amounts, rates, balances, links); if it doesn't have a value on file, it defers to a human instead of guessing. STOP/opt-outs are never answered.
CRM & integrations
Because everything runs over a standard REST API, iBlueText drops into any stack:
- GoHighLevel — trigger sends from workflows and sync replies back as conversations.
- HubSpot / Salesforce — fire a lookup or send on a contact event.
- Zapier / Make / n8n — connect to 5,000+ apps with no code via webhooks.
Native one-click connectors are rolling out — tell us which you need at support@ibluetext.com.
Errors & limits
Errors return a JSON error string with a standard HTTP status:
401 invalid/missing key · 402 out of credits / no line
400 bad request · 404 not found
409 recipient opted out · 429 rate limited
Up to 50,000 numbers per lookup request. Sends are paced by your line's safe throughput. Need higher volume? Add more lines.