PayphonePayphone

Agent Quickstart — Cursor, Claude Code, Codex

What a coding agent needs to wire Dial SMS in under 5 minutes using dial_live_* keys.

Agent Quickstart

Instructions for coding agents (Cursor, Claude Code, Codex) to onboard a human repo with Dial SMS using DIAL_API_KEY — no Privy session refresh.

One-click opens Cursor with a prefilled Payphone setup prompt — review and confirm. Or copy the full setup command for your terminal.

Full setup: pnpm cursor:agent:setup -- --api-key dial_live_… --phone +1… — plugin, Plugin MCP, rules, skills, env, operator policy, and pool test SMS. Then MCP → dial → Login. Skip --with-project-mcp unless you need Installed MCP too.


1. Read machine surfaces first

Fetch these URLs before writing integration code:

ResourceURL
Onboarding manifesthttps://payphone.wtf/.well-known/dial-onboarding.json
Full API (plain text)https://payphone.wtf/llms-full.txt
Skill playbookhttps://payphone.wtf/skill.md
Human quickstarthttps://payphone.wtf/docs/onboarding/quickstart

The manifest includes scopes, routes, self-setup steps, and catalog prices — generated from the same sources as production.


2. Install the skill / plugin

Cursor: use Install in Cursor above, or run from a Payphone clone:

pnpm cursor:agent:setup -- --api-key dial_live_… --phone +1…

Add --with-project-mcp only if you need Installed MCP in addition to the plugin (usually skip — duplicate dial entries). See Agent stack.

ToolCommand
Cursorpnpm cursor:agent:setup or Connect → Skill
Claude Code/plugin install dial@dial-wtf
Codex / OpenCodeCopy .agents/skills/dial/SKILL.md into your project

Optional thin wrapper: .agents/skills/dial-quickstart/SKILL.md — points at manifest + this page.


3. Required environment

The human must set (or you prompt them to set):

export DIAL_API_URL=https://payphone.wtf
export DIAL_API_KEY=dial_live_…
export DIAL_NOTIFY_PHONE=+1…          # operator recipient
# export DIAL_OWNED_LINE_E164=+1…    # only when sending from your leased line

Omit DIAL_OWNED_LINE_E164 for pool send (default). Set it to your active leased E.164 for owned-line send (two-way). Workspace fallback: ownedLineE164 in .payphone/operator-notifications.json.

Default onboarding scopes: account:read, sms:send, numbers:read, numbers:buy.


4. Self-setup loop

Run these steps in order (same as dashboard onboarding blob):

  1. Read https://payphone.wtf/skill.md and /.well-known/dial-onboarding.json → check smsSendModes
  2. Verify key: GET /api/v1/account with Authorization: Bearer $DIAL_API_KEY
  3. Test SMS (pool, default): POST /api/v1/sms/send with { "to": "<user E.164>", "message": "…" }outbound-only; user cannot reply by SMS
  4. Verify credits: GET /api/v1/account/credits
  5. Dedicated line (when SMS replies needed): POST /api/v1/numbers/buy/us → poll GET /api/v1/numbers/buy/status?jobId=… → send via POST /api/v1/numbers/mine/send with { phoneNumber, to, message }
  6. Confirm delivery before saying "done" — see below

Source of truth for step text: buildAgentSetupBlob() in apps/web/lib/onboarding-agent-blob.ts (dashboard copies this for users).


5. Copy-paste prompt for humans

Give your user this block to paste into their agent:

Read https://payphone.wtf/llms-full.txt and
https://payphone.wtf/.well-known/dial-onboarding.json.
Wire deploy-failure SMS alerts into this repo using DIAL_API_KEY
(credits mode). Use POST /api/v1/sms/send for one-way pool alerts.
Buy a dedicated line and use POST /api/v1/numbers/mine/send only if
the user must reply by SMS. Confirm pool sends via GET /api/v1/account/history;
confirm dedicated sends via GET /api/v1/sms/inbox.

6. Delivery is not HTTP 200

POST /api/v1/sms/send → 200 means the message was queued, not that Cheogram delivered it.

Pool vs inbox: GET /api/v1/sms/inbox applies to dedicated lines only. Pool sends have no inbound path — do not expect SMS replies on pool numbers.

Before telling the user "SMS works end-to-end":

  • Pool: Poll messages.status or GET /api/v1/account/history
  • Dedicated line: GET /api/v1/sms/inbox (requires numbers:read) or dashboard threads

7. Example: GitHub Actions failure SMS

- name: SMS on failure
  if: failure()
  env:
    DIAL_API_URL: https://payphone.wtf
    DIAL_API_KEY: ${{ secrets.DIAL_API_KEY }}
  run: |
    curl -sf -X POST "$DIAL_API_URL/api/v1/sms/send" \
      -H "Authorization: Bearer $DIAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d "{\"to\":\"${{ secrets.ALERT_PHONE }}\",\"message\":\"CI failed: ${{ github.workflow }}\"}"

On this page