Gary Club
Resource

SMS

Send outbound and read inbound messages. We route through your configured provider (Telnyx / Signal House) and meter FUEL automatically.

One-off vs broadcast
For 1:1 sends (replies, transactional, post-event), use these endpoints. For list-based blasts (promos, win-backs, drips), use SMS Broadcasts — built-in scheduling, recurrence, approval gating, and per-recipient delivery state.
Bidirectional from one surface
Outbound: POST /v1/sms/messages.
Inbound: subscribe to sms.received via /v1/webhooks — we POST every incoming message to your URL within seconds.

Send a message#

Send outbound SMS

POST/v1/sms/messages
Returns 202 Accepted with a message id and conversation id once the provider has accepted the send. We log a crm_activities row of type sms so it shows up in the contact's timeline. sms.sent webhook fires when the carrier confirms delivery; sms.delivery_failed on rejection.

Body parameters

tostringrequired
E.164 phone number (e.g. +15551234567).
bodystringrequired
Message text. Max 1600 characters.
contact_iduuid
Optional. Links the activity row + sets the contact context.
company_iduuid
Optional. For B2B threads associated to a company.
deal_iduuid
Optional. Pin the message to a specific deal's timeline.
media_urlsstring[]
MMS — provider-dependent. Each URL must be HTTPS and publicly fetchable for ~24h.
Request
curl -X POST https://agency.gary.club/api/public/v1/sms/messages \
  -H "Authorization: Bearer gc_live_EXAMPLE_AbCdEfGhIj0123456789" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+15551234567",
    "body": "Hi Jane — confirming Tuesday at 2pm.",
    "contact_id": "con_EXAMPLE_aaaa"
  }'
FUEL deduction is real-time
On a successful send, your org is charged the per-message rate from your provider's pricing sheet. Out of FUEL? You'll get 402 fuel_exhausted with required + balance in details. Top up at agency.gary.club/dashboard/billing.

List conversations#

List threads

GET/v1/sms/conversations
One row per phone-number ↔ tenant pairing. Sorted by last_message_at desc.

Query parameters

limitintegerdefault: 50
page_tokenstring
statusstring
Filter by conversation status (e.g. open).
phonestring
Substring match on phone_number.
Request
curl "https://agency.gary.club/api/public/v1/sms/conversations?limit=20&status=open" \
  -H "Authorization: Bearer gc_live_EXAMPLE_AbCdEfGhIj0123456789"

Read messages in a thread#

List messages within a thread

GET/v1/sms/conversations/{id}/messages
Cursor-paginated; newest first.

Path parameters

iduuidrequired
Conversation id.

Query parameters

limitintegerdefault: 50
page_tokenstring
Request
curl https://agency.gary.club/api/public/v1/sms/conversations/sc_EXAMPLE_aaaa/messages \
  -H "Authorization: Bearer gc_live_EXAMPLE_AbCdEfGhIj0123456789"

Webhooks for SMS#

  • sms.received — inbound message landed.
  • sms.sent — your outbound was delivered by the carrier.
  • sms.delivery_failed — carrier rejected, opt-out, or DLR fail.
The reply autopilot pattern
Subscribe to sms.received, route the inbound through Claude in n8n, and call back to POST /v1/sms/messages to send the drafted reply. Confirm before sending if you don't fully trust the model.