---
name: platformdtc
description: Run a merchant's real PlatformDTC store with your own tools — products, prices, stock, orders, returns, customers, support and live chat, shipping and selling abroad, email/SMS campaigns, ads, languages, analytics and the storefront theme. Connect https://api.platformdtc.com/mcp as a connector (Claude, ChatGPT, Claude Code, Cursor) or sign in with a link and a pasted code. Use whenever the user asks you to read this skill, or to set up, run, change or check their PlatformDTC store.
---

# PlatformDTC

You run the merchant's **real, live store**: real products, customers and money. Nothing is a
sandbox. Say what you will change before you change it, and answer in the merchant's language.

## 1. Connect (once)

Server: `https://api.platformdtc.com/mcp` (OAuth sign-in; the merchant approves in the browser).
Tell the merchant the steps for the app you run in:

- **Claude** (web/desktop): Customize → Connectors → Add custom connector → paste the server →
  Add → Connect → sign in, pick the store, Approve.
- **ChatGPT**: Settings → Security and login → Developer mode on. chatgpt.com/plugins → + → Add
  custom MCP server → paste the server, Authentication OAuth → Create → sign in, Approve.
- **Claude Code**: `claude mcp add --transport http --scope user platformdtc https://api.platformdtc.com/mcp`,
  then `/mcp` → platformdtc → sign in. **Cursor/others**: add the server URL; it asks to sign in.
- Scripts: a key from **Agents → For developers → API keys** as `Authorization: Bearer sq_agt_…`.

No tool search? Load only the jobs you need: `…/mcp?toolsets=catalog,orders` (sets: `catalog`,
`inventory`, `orders`, `customers`, `marketing`, `subscriptions`, `store`, `shipping`, `analytics`,
`research`, `ads`, `languages`, `schedule`, `theme`, `apps`; `core` always comes along).

**Can't add a connector?** Sign in with a link and a code, then call tools over plain HTTP.

```sh
VERIFIER=$(openssl rand -hex 32)   # secret, this chat only
CHALLENGE=$(printf %s "$VERIFIER" | openssl dgst -sha256 -binary | openssl base64 -A | tr '+/' '-_' | tr -d '=')
echo "https://api.platformdtc.com/oauth/authorize?response_type=code&client_id=dtcmcp_platformdtc_chat&redirect_uri=https%3A%2F%2Fplatformdtc.com%2Foauth%2Fcode&resource=https%3A%2F%2Fapi.platformdtc.com%2Fmcp&code_challenge_method=S256&code_challenge=$CHALLENGE"
```

1. Tell the merchant: "Open this link, sign in, choose your store, click **Approve**, then paste
   the code here." They may untick permissions. The code works once, for 10 minutes.
2. Swap it for a key (`access_token` = `sq_agt_…`, 1 hour, plus `refresh_token`):

```sh
curl -s https://api.platformdtc.com/oauth/token -d grant_type=authorization_code \
  -d client_id=dtcmcp_platformdtc_chat -d redirect_uri=https://platformdtc.com/oauth/code \
  -d code="PASTED_CODE" -d code_verifier="$VERIFIER"
# on 401 later, never ask again; use the newest refresh_token:
curl -s https://api.platformdtc.com/oauth/token -d grant_type=refresh_token \
  -d client_id=dtcmcp_platformdtc_chat -d refresh_token="REFRESH_TOKEN"
```

3. One POST per tool; the answer is `result.content[0].text` (`result.isError: true` = failed, says
   why). Never print the key, refresh token or verifier.

```sh
curl -s https://api.platformdtc.com/mcp -H "Authorization: Bearer $KEY" \
  -H 'Content-Type: application/json' -H 'Accept: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"dtc_whoami","arguments":{}}}'
# "method":"tools/list" lists every tool this connection may call
```

## 2. Start of every session

1. `dtc_whoami` → say which store you are on (`store.name`) and its currency.
2. Your tool list is exactly what the merchant granted. A tool is missing → name the permission
   and ask them to reconnect you with it ticked (Agents → Connect an AI). Never work around it.
3. Before writing copy, read `dtc_get_brand_system`.
4. No clear request? Read `dtc_store_snapshot` and `dtc_heartbeat_get` and suggest the three
   things most worth doing, with the store's real numbers. No products: offer recipe A. Change
   nothing until they pick.

## 3. How changes are approved

| Kind | What happens | What you do |
|---|---|---|
| **Free** (drafts, notes, tags, pausing, lowering a budget) | At once | Do it, report |
| **Propose-first** (`approved_apply`: adding products, collections) | Refused as "propose-only" without `approved_apply: true` | Show what you will add; after a yes, same call with `approved_apply: true` |
| **Confirm** (shoppers see it, money moves, a customer is messaged) | Changes nothing; returns `pending_approval` with summary / impact / before-after | Show it in plain words; after a yes to **that exact action**, call again with `approval_context: {"merchant_confirmed": true}` |
| **Parked** (sends, flows on, publishing, ads on or up, looser ad limits, store rules; with a sign-in connection also every money action and customer message) | `pending_approval` **with a `job_id`**; nothing happened | Say it waits in **Agents → Approvals** (https://platformdtc.com/agents/connect?section=approvals; they also get an email). Don't call again; `dtc_job_wait` shows the result |

- You never approve anything yourself. `dtc_get_approval_rules` shows what will wait.
- **Jobs:** `{job_id, status}` = still running. `dtc_job_wait` until `succeeded`, `failed` or
  `cancelled` (again when `wait_complete: false`). Never say a job is done early.
- **Undo:** every change shows in **Agents → Activity** and `dtc_list_agent_actions`, with
  `undo: {activity_id, can_undo}`. Prices, products, collections, discounts, pages, posts, menus,
  campaign drafts, flows and ad status/budgets can be put back: `dtc_undo_action` first returns
  `put_back`, then confirm. Sends, refunds, charges and deletions can't — say so first.
- **Store limits:** every change you make counts against the store's own limits, shared by all
  its agents (e.g. important settings 10 a day, deletions 50 a day and 500 records, messages to
  customers 100 an hour and 3 a day per customer, bulk 250 records a call). `dtc_get_action_budgets`
  shows what is left. An `AGENT_BUDGET_EXCEEDED` answer is final until the time it names: don't
  retry or split the work to get round it — tell the merchant, who can raise it in Agents → Ask me first.
- **Accounts and passwords never pass through you.** Connecting a payment provider, an ad account,
  a mailbox or a Shopify store answers a dashboard link (`open_this_link` / `open_url`): give it to
  the merchant to open themselves.
- **Retries are safe**; never pass `idempotency_key`. **Errors** are `isError: true` with a code
  (`VALIDATION_ERROR`, `NOT_FOUND`, `FORBIDDEN_SCOPE`, …): fix the call; retry only rate limits/5xx.
- **Money:** quote the tool's amounts (`impact`, `total_formatted`, `next_charge`), never your own
  math. Order money fields are cents (`7000` = 70.00).

## 4. Recipes

**A. Set up a store.** Ask what they sell; use their real products, prices, photos and words.
1. `dtc_upsert_product` makes one in one call: `options`, every variant (`option1`…, `price`,
   `sku`, `inventory_quantity`; stock 0 stops selling unless `inventory_policy: "continue"`),
   `images`, `description`, `seo_title`. New = draft; `status: "active"` sells. Many:
   `dtc_bulk_import_products` (≤200, check each). From Shopify: `dtc_import_products_from_shopify`
   or `dtc_import_products_csv`. Wholesale: `dtc_network_search` → `dtc_network_get_listing` →
   `dtc_network_import_listing`.
2. Collections: `dtc_create_collection`, order with `dtc_set_collection_products`.
3. Theme: follow https://platformdtc.com/skills/platformdtc-theme/SKILL.md (`list_themes` →
   `create_dev_theme` → edit → `check_theme` → `preview_theme`; never edit the live theme).
   `publish_theme` only when asked.
4. `dtc_update_store_policy`; costs `dtc_set_product_costs`, `dtc_set_operating_costs`; domain
   `dtc_add_custom_domain` (a job; give the DNS records).
5. Payments need a verified business: `dtc_start_verification` returns a link for the merchant to
   open (never ask for ID or card details yourself); `dtc_get_verification_status`: `ok` = can take
   payments, `provide_info` = send the link again.
6. A new storefront only when asked: `dtc_create_store` (`name`, `brief`) → `dtc_job_wait`. "A store
   like https://x.com" → add `like_url`; it clones that site exactly, then they replace its text and pictures.

**B. Sell abroad, shipping.** `dtc_get_markets`, `dtc_list_shipping_zones` first. `dtc_update_markets`
(a market = countries paying in its currency; confirm-gated). `dtc_upsert_shipping_zone`: countries
(or `US-CA`; none = everywhere else) + rates in store currency; "free over $60" = `price: 0,
min_subtotal: 60` (paid rate `max_subtotal: 59.99`). Send the whole rate list, keep rate ids, show
before/after, confirm. Never guess a missing number. Tax: `dtc_get_tax_settings`.

**C. Numbers.** `dtc_store_snapshot` (`range` `Today`…`30D`…`YTD` or `from`/`to`) →
`dtc_metrics_catalog` → `dtc_metrics_query` (`report`: `products`, `profit`, `ads_report`, …) →
rows `dtc_metrics_export`. Same as the owner's Analytics. `null` = no data, never zero; profit
needs product costs. Subscriptions: why they cancel `subscription_analytics` /
`subscription_retention`; first actions, expiring cards, saves `subscription_behavior`; churn,
cohorts, win-back `subscription_growth`; failed payments `subscription_retain`; first renewals
that came due and why some were not charged `subscription_first_renewal`. MRR: quote Net MRR
(`net_mrr_cents` / `net_mrr_end_cents`) first, book MRR second. Orders your team must act on (never shipped, label never
scanned, stuck on the way, delivery problem) with what to do: `fulfillment_problems`.

**D. Change an order.** `dtc_get_order` (id or `"#1"`), `dtc_list_orders` (`keyword`, dates,
`status`), `dtc_get_order_shipping` for `order_item_id`s. Swap: `dtc_exchange_order_items`; qty
before shipping: `dtc_edit_order_items`; lost parcel: `dtc_reship_order`; part-ship:
`dtc_fulfill_order` `line_items`; address: `dtc_update_order_shipping_address`; `dtc_cancel_order`;
`dtc_refund_order`. Each previews a price first: show, confirm, call again. No saved card →
`collect: "payment_link"` (`dtc_list_order_payment_links`). Draft invoice:
`dtc_send_draft_order_invoice` (becomes a paid order by itself; don't also complete it).

**E. Support and live chat.** `dtc_list_support_tickets` (`channel: "chat"`/`"sms"`) →
`dtc_get_support_ticket` → `dtc_get_ticket_customer` → `dtc_reply_to_ticket` (a customer message:
confirm or parked, like every email/text to a customer; answer only from what you see, promise no
refunds, discounts or dates) or `dtc_add_ticket_note`.
Chat: `dtc_get_chat_settings` → `dtc_update_chat_settings` (confirm); you answer chats, not
PlatformDTC. Returns: `dtc_create_return` → `dtc_approve_return` → `dtc_mark_return_received`;
refund separately.

**F. Email/SMS campaigns.** `dtc_get_approval_rules`, `dtc_list_segments`, `dtc_list_campaigns`,
then `dtc_create_campaign` with `scheduled_at` (drafts send nothing). Only real offers: the
discount must exist (`dtc_list_discounts`). Send: `dtc_send_campaign` (parked). `already_existed:
true` → edit with `dtc_update_campaign`. Flows: `dtc_create_automation` → `dtc_activate_automation`.

**G. Stock.** `dtc_list_low_stock` → `dtc_suggest_reorder` (no sales = ask how many) →
`dtc_create_purchase_order` (draft; `dtc_list_purchase_order_suppliers`) → show → after a yes
`dtc_send_purchase_order` (emails the supplier) → `dtc_receive_purchase_order`. By hand:
`dtc_set_inventory`, `dtc_adjust_inventory`. `dtc_create_bundle`, `dtc_set_preorder`.

**H. Translate — you write it.** `dtc_list_languages` → `dtc_enable_language` (`code`; hidden) →
`dtc_list_translations` `status: "missing"` then `"needs_review"` (`limit: 200`) → translate each
`source` faithfully, HTML tags intact → `dtc_update_translation` `items: [{type, resource_id,
field, value}]` (≤200). Show a sample, then `dtc_enable_language` `publish: true` (confirm).

**I. Market research** (other stores). `dtc_market_winning_products`, `dtc_market_offers`,
`dtc_market_landing_pages`, `dtc_market_search_ads`, `dtc_market_top_brands` (`niche`, `q`,
`country`, `days`; 30 calls/min). Suggest, never copy text, brands or claims. Any public page:
`dtc_read_web_page` `url` (text, stars, reviews, prices).

**J. Ads.** Facebook: `dtc_meta_connection` → `dtc_meta_launch_sales_campaign` (paused, go-live
parked). Google: `dtc_google_campaign_options` → `dtc_google_create_search_campaign` / `_pmax_` /
`_shopping_`. TikTok: `dtc_tiktok_create_campaign` → ad group → `dtc_tiktok_upload_video` → ad.
Pausing/lowering is at once; on, budget up, or a looser limit (`dtc_meta_set_daily_limit`,
`dtc_meta_set_cpa_ceiling`, `dtc_google_set_limit`, …) is parked. "Stop ads when their page is
down" → `dtc_meta_set_page_guard` `enabled: true` (pauses ads whose landing page fails twice; never
turns them back on; `dtc_meta_resume_page_ads` is parked). Budgets: `"50"` = 50.00/day, said back in money. Ad text only from the merchant; images = their photos via `dtc_meta_upload_image`, shown first.

**K. On a schedule.** "Every Monday tell me…" → `dtc_heartbeat_task_create` (`check` in their
words; a link in it is read fresh each run; `repeat`). Answers on Home and by email, even when you are offline. `dtc_heartbeat_get`: act on
`needs_you`, then `dtc_heartbeat_resolve_item` only after it really happened. Events:
`dtc_list_events` (`after` = `next_cursor`) or `dtc_create_webhook`.

**L. Cited by AI.** `dtc_get_ai_answers` (did ChatGPT, Perplexity, Gemini name the store, what they
cited). Improve pages and posts with real facts; `dtc_add_ai_answers_question` /
`dtc_remove_ai_answers_question`, `dtc_update_ai_answers`.

**M. Digital product.** `dtc_upsert_product`, variant `requires_shipping: false` (optional
`download_limit`, `download_days`) → `dtc_add_digital_file` (public `https://` `url`, ≤2 GB) →
`dtc_list_digital_files` all `ready` → `status: "active"`. Only files the merchant gave you.
Orders: `dtc_get_order_downloads`, `dtc_resend_downloads`, `dtc_release_downloads`, `dtc_revoke_downloads`.

**N. Pay creators per view.** `dtc_get_content_campaign_draft` (best sellers, brief, hashtag, pay,
30 days, suggested budget) → show it → `dtc_create_content_campaign` with just the `budget_cents`
the merchant confirms (any field sent replaces the draft's; it commits money: confirm first) →
live on platformdtc.com/rewards (`public_url`). `dtc_list_content_posts` `status: "review"` →
`dtc_approve_content_post` (confirm) or `dtc_reject_content_post`. Pay: `dtc_list_content_creators`
→ the merchant pays → `dtc_record_content_payout` (moves no money).

**O. Store details, domains and code on the storefront.** `dtc_get_store_settings` →
`dtc_update_store_settings` (a new name, contact email, currency or country rewrites the written
policies, and prices are NOT converted — say so; confirm-gated). Domains: `dtc_list_domains` →
`dtc_set_primary_domain`, `dtc_set_domain_mode`, `dtc_redirect_all_domains_to_primary`,
`dtc_remove_domain` (each can take the store offline: show the before → after, confirm).
Search listing `dtc_update_store_seo`; automatic collections `dtc_update_collection_rules`; many
products at once `dtc_bulk_edit_products` (≤100, partial fields); scripts on the storefront
`dtc_add_script_tag` (https only, confirm — only scripts the merchant names); custom fields
`dtc_set_metafield`; speed `dtc_get_storefront_speed`.

**P. How the store gets paid, fraud and checkout.** `dtc_get_payment_settings` (card provider,
methods, failover, every connected provider) → `dtc_update_payment_settings`,
`dtc_set_payment_method` (Klarna, Afterpay…), `dtc_set_refused_cards`; fraud and dispute
automations `dtc_get_fraud_automations` → `dtc_update_fraud_automation`; automatic dispute
evidence `dtc_update_dispute_settings`. All change real money flow: confirm, and they may be
parked. Checkout look: `dtc_get_checkout_design` → `dtc_update_checkout_design` (a draft) →
`dtc_publish_checkout_design`. Embedded checkout `dtc_create_checkout_embed`. Tracking pixels
`dtc_list_tracking_pixels` → `dtc_create_tracking_pixel` → `dtc_send_tracking_pixel_test_event`.
Payment fees for profit `dtc_set_payment_fee`.

**Q. Subscriptions day to day, POS and after-purchase offers.** Failed payments:
`dtc_get_subscription_settings` (retries, reminder emails) and `dtc_send_subscription_card_request`
(asks one customer for a new card). Add-ons and one-time items `dtc_add_subscription_addon` /
`dtc_add_subscription_one_time_item` (show the next charge before → after). Many at once:
`dtc_bulk_reschedule_subscriptions`, `dtc_bulk_change_subscription_price` (≤250, confirm).
Rules that run on their own `dtc_create_subscription_automation_rule`. In store:
`dtc_list_pos_locations`, `dtc_open_cash_drawer`, `dtc_create_pos_sale`. The default
after-purchase offer `dtc_get_default_upsell_offer` → `dtc_update_default_upsell_offer` — turning
on "also subscribe" halved acceptance before: ask first.

**R. Customers, orders housekeeping and moving from Shopify.** New email to a customer
`dtc_start_support_email` (parked or confirmed like replies). Marketing consent
`dtc_opt_in_customers_to_marketing` only with how they agreed (`consent_source`, `evidence`);
`dtc_opt_out_customers_from_marketing` at once. Privacy request `dtc_request_customer_data`.
Orders: `dtc_archive_orders`, `dtc_cancel_orders` (refunds, ≤250, confirm), `dtc_export_orders`,
`dtc_list_fulfillment_problems`. Ship-from address `dtc_set_ship_from_address`. Shopify move:
`dtc_get_store_migration` → `dtc_start_store_migration`; switching on moved subscriptions charges
cards (`dtc_activate_store_migration_subscriptions`, parked).

**S. Email and text sending.** Sending domain `dtc_list_email_domains` → `dtc_add_email_domain`
(give the merchant the DNS records) → `dtc_check_email_domain`. Before a send:
`dtc_estimate_send_cost`; a test to the team only `dtc_send_marketing_test`. Results per flow
`dtc_get_automation_report`, per campaign `dtc_get_campaign_report`. Texts: daily cap
`dtc_get_sms_limits`, replies `dtc_list_sms_conversations` → `dtc_reply_sms_conversation`.

## 5. Where to find the rest

Entry tools; tool search / `tools/list` has the rest.

- **Catalog:** `dtc_list_products`, `dtc_update_product`, `dtc_bulk_update_variants`, `dtc_set_product_images`, `dtc_get_product_feeds`
- **Orders & money:** `dtc_list_orders`, `dtc_list_draft_orders`, `dtc_list_disputes`, `dtc_list_flagged_orders`, `dtc_get_balance`, `dtc_list_payouts`, `dtc_referral_status`
- **Customers:** `dtc_list_customers`, `dtc_tag_customers`, `dtc_list_subscriptions`, `dtc_list_members`, `dtc_list_product_reviews`, `dtc_get_buyer_survey_results`
- **Shipping:** `dtc_list_shipments` (`lens: "late"`), `dtc_list_returns`, `dtc_list_order_fulfillment_orders`, `dtc_list_pos_sales`
- **Marketing:** `dtc_list_automations`, `dtc_list_gift_cards`, `dtc_list_upsell_funnels`, `dtc_get_showcase` / `dtc_update_showcase` (`{enabled: true}` lists the store on platformdtc.com/made-with, results as ranges; ask first), `dtc_list_affiliates`, `dtc_get_affiliate_marketplace` / `dtc_set_affiliate_marketplace` (`{listed: true}` alone = program on with defaults, listed on platformdtc.com/earn; confirm first), `dtc_whatsapp_status`, `dtc_social_list_posts`, `dtc_list_content_campaigns`
- **Store & checkout:** `dtc_get_checkout_settings`, `dtc_list_notification_templates`, `dtc_list_store_pages`, `dtc_list_menus`, `dtc_get_costs`
- **Store setup:** `dtc_get_store_settings`, `dtc_list_domains`, `dtc_get_payment_settings`, `dtc_get_fraud_automations`, `dtc_get_checkout_design`, `dtc_list_tracking_pixels`, `dtc_list_installed_apps`, `dtc_get_action_budgets` (what agents may still change today)
- **Subscriptions & in store:** `dtc_get_subscription_settings`, `dtc_list_subscription_automation_rules`, `dtc_list_pos_locations`, `dtc_get_default_upsell_offer`
- **Sending:** `dtc_list_email_domains`, `dtc_get_automation_report`, `dtc_get_campaign_report`, `dtc_list_sms_conversations`
- **Ads:** `dtc_google_connection`, `dtc_tiktok_connection`, `dtc_meta_get_daily_limits`

## 6. Never

- Invent data: no placeholder text, fake reviews, ratings, stock, prices, GTINs or claims.
  Unknown → leave it out and ask.
- Message customers without a real reason and consent, or get round a STOP.
- Refund, charge, cancel as fraud or spend on your own judgement.
- Look for a way around a missing permission or an approval.

## 7. When you finish

Say what changed (with links), what waits for approval and where, and what you need from them.
