Gentic SMS Marketing — Documentation
Connect any AI agent to your Postscript SMS list. Sync your subscribers and keywords into your organization's Brain, then ask the questions a subscriber list can actually answer: what share of revenue comes from SMS subscribers, how fast the list is growing and what the opt-out rate is, whether SMS opt-in tracks better retention, and which keywords are genuinely growing the list. Bounded, resumable syncs keep it current without re-reading everything.
1. Getting Started
Sign Up & Get Your API Key
Before you can use Gentic SMS Marketing, you need an API key to authenticate your requests.
- Go to gentic.co/sms-marketing and create an account.
- Create an organization from your dashboard. API keys and billing are scoped to the organization.
- Generate an API key and use it as a Bearer token in your MCP client.
2. Connecting to the MCP Server
The server is available at https://mcp.gentic.co/sms-marketing. For Claude Code:
claude mcp add gentic-sms-marketing \
--transport http \
https://mcp.gentic.co/sms-marketing \
--header "Authorization: Bearer YOUR_API_KEY"For Claude Web and ChatGPT you can also connect via OAuth — no API key needed. See the connect section on the landing page for other MCP clients (n8n, OpenClaw).
3. Agent Skill
For the best results, pair the MCP server with the Gentic SMS Marketing agent skill. The MCP server gives your agent tool access; the skill teaches it the optimal workflow order. Both the raw SKILL.md and a ready-to-upload .skill bundle are generated on demand from the live manifest, so they always reflect the current tools and pricing.
Add the skill directly via URL:
https://gentic.co/sms-marketing/SKILL.mdOr upload a .skill bundle to Claude Managed Agents:
https://gentic.co/sms-marketing/gentic-sms-marketing.skillDownload this file and upload it wherever Claude Managed Agents asks for a .skill file. It's a zip bundle generated on demand from the latest SKILL.md.
4. When to Apply
- User wants to know what share of revenue or AOV comes from SMS subscribers.
- User wants list growth and opt-out rate over time.
- User wants to know whether SMS subscribers retain or resubscribe better than non-subscribers.
- User wants to know which keywords or sign-up sources are actually growing the list.
- User wants to sync their Postscript subscriber list into their Brain for analysis.
- User wants to join SMS opt-in status against orders, subscriptions, loyalty or survey data.
5. Workflow
1. Connect Postscript once, then sync without credentials
The SMS Marketing server sources the Postscript connection (the Private API key) from the org's connected integration (Gentic dashboard → Integrations → Postscript). You never pass credentials to the tools. Call `postscript_connection_status` first — it's free and returns `{ connected, shop_id, shop_name, checked_live }`. Pass `check_live` when you want it to actually probe Postscript rather than just report that a key is stored; that distinguishes a credentials problem from an empty result, which is the ambiguity worth resolving before you debug a sync.
2. ⚠️ Know what this domain does NOT have, before you promise it
Postscript's API exposes **no campaign, automation or message-performance data at all**. No tool here can tell you how a send performed — open rate, click rate, revenue per message, none of it exists to read. If the user asks about SMS campaign performance, say so plainly and point them at `klaviyo_report` on the `/email-marketing` domain. Answering with subscriber-list numbers dressed up as campaign results is worse than saying it isn't available.
3. Sync the subscriber list with `postscript_sync`
`postscript_sync` is **free** and READ-ONLY. It warehouses `postscript_subscribers` (id, ps_id, email, shopify_customer_id, per-channel opt-in status, tags, custom properties) and `postscript_keywords`, upserted on their id so a re-sync refreshes rows in place. Two retention details worth knowing before you interpret the tables: opted-out subscribers are **included**, so the table is the churn record as well as the active list; and keywords are never deleted from the table, so a keyword removed in Postscript stays as a historical row.
4. Phone numbers and names are scrubbed before anything is written
Numbers and customer names never reach the warehouse — they're removed on ingest, and the removed field names come back in `scrubbed_keys` and are recorded on each row. That's deliberate: the list is analysable without warehousing contact details. It also means this domain cannot be used to retrieve someone's phone number, and a request to do so should be declined rather than worked around.
5. Walk the list with bounded, resumable pagination
Each `postscript_sync` call is BOUNDED: it pages until `max_pages_per_run` pages OR `max_seconds_per_run` seconds, then returns `has_more` and a `next_cursor`. Call again passing that back as `cursor` until `has_more` is false; `total_pages` tells you how far the walk still has to go. The result also carries `rate_limited_retries` — how many times the run was rate-limited and retried. It's the field that tells a short run apart from a throttled one: Postscript's page size is fixed at 25 and cannot be raised, so when that count is high the answer is to keep calling, not to raise the bounds. Use `resources` to sync only the table you need, and `updated_since` for an incremental refresh rather than a full backfill.
6. Count and aggregate with `query_data`
The SMS tools warehouse data; they don't analyze it. For subscriber counts, list growth, opt-out rate, or SMS-subscriber revenue share, use `query_data` (Gentic Data MCP) over `postscript_subscribers` and `postscript_keywords` — standard SQL GROUP BY / COUNT / SUM. Sync first (or re-sync incrementally) so the numbers are current.
7. Join against the rest of the business — this is the point
A subscriber list on its own gives you growth and opt-out rate. Everything more interesting comes from the join, and `shopify_customer_id` is already on the row: against orders for SMS-subscriber revenue share and AOV versus non-subscribers, against subscription tables (`skio_*` / `loop_*`) for whether SMS opt-in tracks retention, against loyalty (`rivo_*`) for whether your SMS list and your VIPs are the same people. Compose it with `query_data`.
8. Present results clearly
Don't dump raw JSON. Summarize the numbers — subscriber counts, growth, opt-out rate, revenue share — and cite them. After a sync, say how many rows landed per table and **how far through the walk you are** — `has_more` together with `total_pages`, never `has_more` alone. The boolean reads the same at 1% and at 99%, so “there’s more to page through” sounds like nearly-done when it can mean thousands of pages remain; at a fixed 25 records per page that difference is the whole answer. Also mention `rate_limited_retries` when it's non-zero, because it explains a run that returned less than expected. If the question was about campaign performance, lead with the fact that this data doesn't exist here rather than burying it under numbers that don't answer it.
6. Tool Reference
2 tools, rendered live from the Gentic MCP manifest. Parameter tables come directly from each tool's JSON Schema.
postscript_connection_status
Check whether this organization has Postscript connected and whether the stored API key still works. Returns `{ connected, shop_id, shop_name, checked_live }`. Use this before `postscript_sync` when a sync has failed, to tell a credentials problem apart from an empty result. Note that Postscript's API has no campaign or message-performance data at all, so no tool in this domain can report how an SMS send performed — for SMS campaign stats use `klaviyo_report`. FREE.
| Parameter | Type | Description |
|---|---|---|
check_live | boolean | Make one real call to Postscript to verify the key still works (default false). The call reads only the shop's own identity — no subscriber data. |
postscript_sync
Sync this organization's Postscript SMS subscriber list into its data backend — READ-ONLY, one BOUNDED chunk per call. Uses the org's connected Postscript integration (dashboard → Integrations; no API key is passed here). Warehouses `postscript_subscribers` (id, ps_id, email, shopify_customer_id, per-channel opt-in status, tags, custom properties) and `postscript_keywords`, upserted on their id so re-syncs refresh rows in place. Keywords are never removed from the table, so a keyword deleted in Postscript remains as a historical row. The subscriber list is the product here: joined to your Shopify orders it gives SMS-subscriber revenue share and AOV versus non-subscribers, joined to subscription or loyalty tables it shows whether SMS opt-in tracks retention, and on its own it gives list growth and opt-out rate over time. Opted-out subscribers are INCLUDED, so the table is the churn record as well as the active list. Postscript's API exposes no campaign, automation or message-performance data, so there is nothing here about how a send performed — for SMS campaign stats use `klaviyo_report`. Query these tables with `query_data`; that is the analytics surface. Phone numbers and customer names are never stored: they are removed before anything is written, and the removed field names are returned in `scrubbed_keys` and recorded on each row. BOUNDED + RESUMABLE: each call pages until `max_pages_per_run` pages OR `max_seconds_per_run` seconds, then returns `has_more` + `next_cursor`. Call again passing that back as `cursor` until `has_more` is false. `total_pages` shows how far the walk has to go. FREE.
| Parameter | Type | Description |
|---|---|---|
resources | string[] | Subset of resources to sync this run: subscribers, keywords. Omit to sync both. Keywords are small and unpaginated; subscribers is the long walk. |
updated_since | string | Only fetch subscribers updated at or after this time (ISO-8601). Omit for the initial full backfill; on later runs omit it too and the sync derives its own starting point from what is already stored, reaching back 48 hours for safety. Pass an explicit value to override that. |
max_pages_per_run | integer | Cap on pages fetched this call (default 40, hard max 200). Postscript's page size is fixed at 25 records and cannot be raised. Page more via next_cursor, never via a bigger run. 1 – 200 |
max_seconds_per_run | integer | Wall-clock budget for this call (default 60s, hard max 240s). With a fixed 25-record page this is usually the bound that bites first. 5 – 240 |
cursor | any | Pass back the `next_cursor` from the previous call, exactly as returned. It carries the filter as well as the position — Postscript's own cursor does not, so a hand-edited cursor is refused rather than silently walking a different list. |
7. Pricing
Pricing is pulled live from the Gentic MCP manifest. All prices are per call and deducted from your Gentic credits.
| Tool | Cost |
|---|---|
| postscript_connection_status | Free |
| postscript_sync | Free |
8. Notes
- Organization-scoped: the Postscript connection comes from the org's connected integration (dashboard → Integrations → Postscript). No credential is ever passed to the tools.
- Cost: both `postscript_connection_status` and `postscript_sync` are **free**. You pay only for analytics you run over the synced data (e.g. `query_data`). Pricing is pulled live from the Gentic MCP manifest.
- **No campaign or message-performance data exists in Postscript's API** — nothing here reports how a send performed. For SMS campaign stats use `klaviyo_report` on the `/email-marketing` domain.
- `postscript_sync` is READ-ONLY: it never sends a text, never edits a subscriber, and never writes back to Postscript.
- Phone numbers and customer names are removed before anything is written; the removed field names are returned in `scrubbed_keys` and recorded on each row.
- Opted-out subscribers are included in `postscript_subscribers`, so the table is the churn record as well as the active list.
- Keywords are never removed from `postscript_keywords`: a keyword deleted in Postscript remains as a historical row.
- Syncs are bounded and resumable: each call stops at `max_pages_per_run` / `max_seconds_per_run` and returns `has_more` + `next_cursor`; pass it back as `cursor` until `has_more` is false. `total_pages` shows the remaining distance, `rate_limited_retries` reports how often the run was rate-limited and retried, and `updated_since` gives an incremental refresh instead of a full backfill.
- The two tables — `postscript_subscribers` and `postscript_keywords` — are queried with `query_data` for all counts and aggregations.