← Back to blogcannabis

Send SMS Pickup Notifications from Flowhub Without Getting Banned by Twilio

May 26, 2026 · Android Texter

Send SMS Pickup Notifications from Flowhub Without Getting Banned by Twilio

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

  1. Why every SMS provider rejects cannabis
  2. How Android Texter solves it
  3. Architecture overview
  4. Step 1 — pair an Android phone to Android Texter
  5. Step 2 — get your Flowhub API credentials
  6. Step 3 — build the n8n workflow
  7. Step 4 — write the SMS template
  8. Step 5 — test the end-to-end flow
  9. Going further: loyalty, refills, METRC alerts
  10. 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:

  1. 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.
  2. 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.

  1. Sign up at androidtexter.com using "Continue with Google"
  2. Dashboard → DevicesAdd Device
  3. 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.
  4. Grant SMS, Contacts, and notification permissions when prompted.
  5. 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:

  1. Settings → API & Integrations (or Account → Developer)
  2. Generate a new API key, scope it to "Read Orders" + "Read Customers"
  3. Copy the API key and your Flowhub location/clientId
  4. 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 ID
    • status: READY_FOR_PICKUP
    • limit: 50
    • sort: 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

  1. In Flowhub, manually move a test order to status READY_FOR_PICKUP (or wait for a real one to land)
  2. n8n logs the workflow execution within 2 minutes (n8n → Executions tab)
  3. Android Texter dashboard → Messages shows the outbound message queued, then sent, then delivered
  4. 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 shows failed, 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 casen8n triggerSMS body
Loyalty milestoneSchedule: every 1h; query customers with loyaltyPoints > X not texted in 30 days"Hi {{first_name}}, you have {{points}} points to redeem at {{location}}."
Refill reminderSchedule: every 1h; query orders 25-30 days old"Hi {{first_name}}, time to restock? Your last order was 28 days ago."
Curbside arrivalWebhook 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 alertSchedule: daily; query for products approaching expiration(Staff alert SMS, not customer-facing)
Promotion blastManual trigger; query opted-in customersUse 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.