If you run a cannabis dispensary on Flowhub, you've probably already hit this wall: every major SMS provider rejects cannabis. Twilio classifies it as SHAFT-C ("Sex, Hate, Alcohol, Firearms, Tobacco, Cannabis") and won't approve 10DLC registration for dispensaries. Same story with Bandwidth, Sinch, Plivo, and every other carrier-grade A2P provider.
So you're stuck calling customers to tell them their pre-order is ready, or hoping they check the email they used to sign up. Email open rates run about 20%. Phone calls take staff time you don't have. SMS open rates are 98% but you can't send any.
There's a workaround that doesn't require dishonest 10DLC paperwork or hiding your business: send SMS from a real Android phone you already own. Carrier networks treat consumer-handset SMS as person-to-person traffic, the same as the texts your front-desk staff send their friends on their personal phones. They can't reject it because the messages look identical to legitimate consumer SMS.
This guide walks through wiring Flowhub's order events to outbound SMS using Android Texter as the gateway and n8n as the no-code glue in the middle. Total setup time: about an hour. No A2P registration, no broker contracts, no per-message fees.
Table of contents
- Why every SMS provider rejects cannabis
- How Android Texter solves it
- Architecture overview
- Step 1 — pair an Android phone to Android Texter
- Step 2 — get your Flowhub API credentials
- Step 3 — build the n8n workflow
- Step 4 — write the SMS template
- Step 5 — test the end-to-end flow
- Going further: loyalty, refills, METRC alerts
- Cannabis SMS compliance FAQ
Why every SMS provider rejects cannabis
A2P 10DLC is the framework US carriers use to vet business-to-consumer SMS. Every business that wants to send marketing or transactional texts has to register their use case, pay registration fees to The Campaign Registry (TCR), and get approval from each carrier.
The SHAFT-C classification automatically rejects:
- Cannabis (recreational AND medical, in all 50 states, regardless of state legality)
- Sex-related products
- Hate speech / political extremism
- Alcohol (some carriers approve with age-gating)
- Firearms
- Tobacco / vaping
Even if your dispensary is fully licensed under your state's program, the federal classification of cannabis triggers automatic SHAFT-C denial across the board. Carriers don't care about state legality — they care about federal Schedule I status.
There are a handful of "cannabis-friendly" SMS providers (Klaviyo SMS opened some cannabis use cases briefly, Springbig and Sweetspot exist for cannabis loyalty), but they generally:
- Charge $0.02-$0.05 per message (vs. ~$0 with Android Texter)
- Require minimum monthly commitments
- Restrict you to "transactional only" — no promotions, no loyalty blasts, no events
- Can pull the plug at any time when carriers crack down
Even the cannabis-specific providers ride on top of the same carrier networks that classify cannabis as SHAFT-C. They're one carrier-policy change away from shutting your account off.
How Android Texter solves it
Android Texter is a self-hosted SMS gateway that uses an Android phone you already own. The phone uses its existing carrier SIM and sends text messages exactly the way you do when you text a friend. There's no A2P 10DLC registration because there's no A2P traffic — every message originates from a real consumer handset.
For carriers, the message is indistinguishable from your front-desk staff texting their roommate. They can't reject it because rejecting it would mean rejecting all consumer SMS, which would break their network.
Architecture:
Flowhub (order.completed event via API polling or webhook)
│
▼
n8n workflow (cron polls Flowhub for new ready orders)
│
▼
Android Texter API (HTTPS, X-API-Key auth)
│
▼
FCM push to your paired Android phone
│
▼
Phone sends actual SMS to customer's number
The phone is the gateway. n8n is the orchestration. Android Texter is the bridge between your software stack and the phone.
Pricing: Android Texter is $10/month per phone after a free tier.
Unlimited messages within your carrier's per-day cap (typically
250-1,000 messages/day for consumer lines). For a dispensary doing
50-150 SMS-eligible orders per day, one phone covers it. Larger ops
pair multiple phones and Android Texter load-balances across them
automatically.
Architecture overview
Flowhub's REST API exposes order data. You query for orders with
status Ready for Pickup (or whatever your dispensary calls that
stage), grab the customer phone number, and POST a "your order is
ready" SMS to Android Texter.
Two ways to fire the SMS at the right moment:
- Polling — n8n cron triggers every 2 minutes, queries Flowhub for orders that changed status since last check, fires SMS for new ones. Simple, reliable. We'll use this.
- Webhooks — if your Flowhub plan includes outgoing webhooks,
subscribe to
order.statusChanged. Lower latency. More setup. See the FAQ section.
We'll use polling for this guide because it works on every Flowhub plan and the latency difference (sub-2-minute SMS vs. sub-5-second) doesn't matter for pickup notifications.
Step 1 — pair an Android phone to Android Texter
You'll need any Android phone running Android 8.0 or newer, with an active SIM that can send SMS, and a free Android Texter account.
- Sign up at androidtexter.com using "Continue with Google"
- Dashboard → Devices → Add Device
- A QR code appears. Install the Android Texter app on the phone (download at androidtexter.com/download), open it, and tap the QR scanner button.
- Grant SMS, Contacts, and notification permissions when prompted.
- The dashboard shows the phone as Online within 30 seconds.
Park the phone somewhere it'll stay charged and have WiFi. It can be locked, in a drawer, in a back office — it just needs to wake up to send messages, which happens via Firebase Cloud Messaging push.
Step 2 — get your Flowhub API credentials
In your Flowhub admin console:
- Settings → API & Integrations (or Account → Developer)
- Generate a new API key, scope it to "Read Orders" + "Read Customers"
- Copy the API key and your Flowhub location/clientId
- Save both — you'll paste them into n8n in the next step
Flowhub's API base URL is https://api.flowhub.co (or your
white-labeled equivalent). The endpoint we'll hit is GET /v0/orders
with a filter for status=READY_FOR_PICKUP.
Step 3 — build the n8n workflow
If you don't have n8n yet, the fastest path is to use their cloud trial at n8n.cloud (14 days free) or self-host on a $5 DigitalOcean droplet for full control.
Install the Android Texter community node:
# In your n8n instance (Settings → Community Nodes → Install)
npm install @andysmith/n8n-nodes-android-texter
Or click through n8n's UI: Settings → Community Nodes → Install →
paste @andysmith/n8n-nodes-android-texter → install.
Now build the workflow:
Trigger: Schedule (every 2 minutes)
Drop a Schedule Trigger node onto the canvas. Set interval to
2 minutes.
Step 1: Track last-seen order ID (n8n Static Data)
We need to remember which orders we've already sent SMS for. Use n8n's
Static Data node (or a Set node feeding into Function) to read
the lastSeenOrderId from the workflow's static storage at the start
of each run.
Step 2: HTTP Request — fetch Flowhub orders
Add an HTTP Request node:
- Method:
GET - URL:
https://api.flowhub.co/v0/orders - Headers:
Authorization: ApiKey YOUR_FLOWHUB_API_KEY - Query Parameters:
clientId: your Flowhub location IDstatus:READY_FOR_PICKUPlimit:50sort:createdDate:desc
This returns the most recent 50 ready-for-pickup orders. We'll filter to only the new ones.
Step 3: Function — filter to new orders
Add a Function node to compare returned order IDs against
lastSeenOrderId:
const lastSeen = $node["Static Data"].json.lastSeenOrderId || '';
const orders = $input.all().map(i => i.json);
const newOrders = orders.filter(o => o.id > lastSeen);
// Update the marker so next run only picks up newer orders
if (newOrders.length > 0) {
await this.helpers.setStaticData({
lastSeenOrderId: newOrders[0].id // most recent ID
});
}
return newOrders.map(o => ({ json: o }));
Step 4: Android Texter — Send SMS
Add the Android Texter node from the community node you installed:
- Operation: Send SMS
- Phone Number:
={{ $json.customer.phoneNumber }} - Message:
={{ "Hi " + $json.customer.firstName + ", your order is ready for pickup at " + $json.location.name + ". Show this text + ID. Reply STOP to opt out." }}
That's the entire workflow. Save it, activate it. It'll poll every 2 minutes and fire SMS to customers as their orders go ready.
Step 4 — write the SMS template
A few notes on the SMS body that matter for cannabis specifically:
Don't say "cannabis" or "marijuana" in the message. Even though the message is coming from a consumer handset and carriers can't reject it, some carrier spam filters scan content for keywords. Stick to neutral language: "your order," "your pickup," "your appointment."
Include an opt-out. "Reply STOP to opt out" — this isn't a carrier requirement on consumer SMS the way it is for A2P, but it's good TCPA hygiene and your customers expect it.
Identify yourself. Lead with the store name (or use the customer's first name + store location). One-line context, then the action.
Good template:
Hi Sarah, your pickup is ready at Green Leaf Boulder. Bring your ID
- order #4521. Open 9am-10pm today. Reply STOP to opt out.
Bad template:
🌿💚 YOUR CANNABIS ORDER IS READY 💨💨 SAVE 20% ON YOUR NEXT EDIBLES! CLICK HERE → bit.ly/4xy7z
The first one looks like a normal business SMS. The second one looks exactly like the spam carriers' filters are trained to catch, even from consumer numbers.
Step 5 — test the end-to-end flow
- In Flowhub, manually move a test order to status
READY_FOR_PICKUP(or wait for a real one to land) - n8n logs the workflow execution within 2 minutes (n8n → Executions tab)
- Android Texter dashboard → Messages shows the outbound message queued, then sent, then delivered
- The test customer's phone receives the SMS
If anything errors:
- n8n times out talking to Flowhub → Flowhub API key wrong or rate-limited. Their limits are around 100 req/min on standard plans.
- n8n calls succeed but no SMS arrives → check the Android Texter
dashboard for the message. If it's stuck in
queued, the paired phone might be offline. If it showsfailed, the customer phone number was malformed. - SMS sends but goes to spam on customer's phone → almost always because the message body looked promotional. Tone it down.
Going further: loyalty, refills, METRC alerts
The polling pattern extends to every Flowhub data point:
| Use case | n8n trigger | SMS body |
|---|---|---|
| Loyalty milestone | Schedule: every 1h; query customers with loyaltyPoints > X not texted in 30 days | "Hi {{first_name}}, you have {{points}} points to redeem at {{location}}." |
| Refill reminder | Schedule: every 1h; query orders 25-30 days old | "Hi {{first_name}}, time to restock? Your last order was 28 days ago." |
| Curbside arrival | Webhook from your curbside check-in form (Typeform, etc.) | "Sarah arrived in lot for order #4521." (this one goes to your staff, not the customer) |
| METRC compliance alert | Schedule: daily; query for products approaching expiration | (Staff alert SMS, not customer-facing) |
| Promotion blast | Manual trigger; query opted-in customers | Use the Send Broadcast module — up to 500 recipients per call with {{first_name}} substitution per recipient |
For the broadcast use case specifically, install the Android Texter
node's "Send Broadcast" action and pass an array of phone numbers
along with a templated message body. Android Texter's broadcast
endpoint substitutes {{first_name}}, {{last_name}}, and other
contact fields per-recipient from contact records you've upserted.
Cannabis SMS compliance FAQ
Is sending SMS from a paired phone legal for cannabis? Yes. The Telephone Consumer Protection Act (TCPA) governs commercial SMS based on consent, not on the delivery mechanism. As long as the customer opted in to receive texts from your dispensary (typically collected at checkout or signup), texting them from a consumer handset is legal. Carriers' A2P 10DLC restrictions are carrier policy, not federal law — and they don't apply to person-to-person traffic.
Do I need explicit SMS opt-in? Yes, for any marketing or promotional SMS. Transactional notifications (order ready, refill reminder, account updates) typically fall under an implied consent if the customer provided their phone number for that purpose. Get a lawyer's review for your state — cannabis-friendly attorneys exist in every legal state and they're cheap insurance.
What about state-level cannabis advertising restrictions? Each state's cannabis regulator (CCC in MA, BCC in CA, MED in CO, etc.) has its own rules about how dispensaries can advertise. Pickup-ready and refill-reminder texts to existing customers are almost always allowed; promotional blasts to opted-in customers are usually allowed; sending unsolicited promotional texts is usually prohibited. Check your state's rules.
What if I want webhooks instead of polling?
Flowhub's Enterprise plan includes outgoing webhooks. Subscribe to
order.statusChanged and skip the n8n schedule trigger entirely.
The middleware logic is the same; only the trigger changes. See our
LoanPro webhook guide for the
webhook + Cloudflare Worker pattern that translates directly.
Can I use Treez/Cova/Greenbits/Dutchie instead? Same pattern. Any cannabis POS with a REST API or webhooks works the same way. We have separate guides in progress for each — sign up below and we'll email you when they're published.
What's my carrier daily limit? Most US carriers throttle consumer lines to 250-1,000 outgoing SMS per day before flagging the number for "spam-like behavior." For a high-volume dispensary, pair 2-3 phones — Android Texter auto-load-balances and Pro plan supports unlimited devices.
What if my paired phone breaks or gets stolen? Open the Devices page, delete the lost device, and pair a new one in 30 seconds. Your account, contacts, and message history live server-side — nothing on the lost phone matters.
