422 contact_opted_out. There’s no way to bypass this server-side.
This isn’t just hygiene — it’s how you stay TCPA-compliant for US recipients. Opt-out enforcement is non-negotiable.
What triggers an opt-out
Inbound STOP-pattern keyword
The most common path. When an inbound message body matches one of the recognized keywords (case-insensitive, exact-match after stripping whitespace), iBubbl auto-marks the contact opted out and fires acontact.opted_out webhook with source: "auto_keyword".
Recognized keywords:
stopunsubscribecancelendquitstopall
.strip().lower(). Common false-positive patterns like "STOP! that's hilarious" or "please stop sending" do not match — they don’t equal the keyword exactly.
If you need broader pattern handling, post-process inbound webhooks yourself and have your rep mark the contact opted out from the dashboard.
Manual dashboard opt-out
A rep can mark a contact opted out from the dashboard’s contact detail view. Acontact.opted_out webhook fires with source: "manual".
GoHighLevel Do Not Disturb
If your account is connected to a GoHighLevel sub-account, marking a contact Do Not Disturb there (for SMS or all channels) opts them out in iBubbl too. The webhook fires withsource: "ghl_dnd".
Through the API
POST /v1/contacts/{id}/opt-out records an opt-out from your own system, for example one collected in your CRM, by email or on a call. The webhook fires with source: "api". Calling it for someone already opted out (in any way) answers 200 and fires nothing.
What happens after opt-out
- All
POST /v1/messagesto the contact return422 contact_opted_out. - Automation (workflow) sends to the contact are refused the same way.
- The contact remains visible in your dashboard with an opted-out badge, and
opted_outistrueon the contact. - The opt-out belongs to the phone number, not the contact. It matches every form of the number (
+14155551234and4155551234are the same person). If you delete the contact and the number comes back as a new contact, the new one starts withopted_out: trueand sends are still refused.
Re-opting in
An opt-out can’t currently be undone — not through the API and not from the dashboard. This is deliberate: accidental or automated re-opt-ins are a compliance risk. If a contact was opted out by mistake, email support@ibubbl.com.Detecting opt-outs in your integration
The cleanest path is thecontact.opted_out webhook — you’ll see it shortly after the opt-out happens, with the source. It fires once per person, the first time they opt out.
If you can’t run webhooks, list opted-out contacts with GET /v1/contacts?opted_out=true, or check opted_out on each contact response:
Block or opt out
Both stop one-to-one sends, but they are different things:
A contact can be both. Sends then return
contact_opted_out.

