API Keys (Long-Lived Bearer)
Mint dial_live_* keys from the dashboard for bots and scripts that cannot refresh a Privy session every hour.
API Keys (Long-Lived Bearer)
Use dial_live_* API keys when you need a credential that survives
restarts, cron jobs, and server-side clients (Elixir, Python, Node) without
re-implementing Privy session refresh.
Mint keys from /dashboard/billing under the API
Keys card. The secret is shown once at creation — copy it immediately.
Quickstart
# 1. Verify the key
curl -sS "https://payphone.wtf/api/v1/account" \
-H "Authorization: Bearer dial_live_YOUR_KEY"
# 2. Send a pool SMS
curl -X POST https://payphone.wtf/api/v1/sms/send \
-H "Authorization: Bearer dial_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"to":"+15125551234","message":"hello from my bot"}'SDK
import { DialClient } from "@dial/api";
const dial = new DialClient({
baseUrl: "https://payphone.wtf",
auth: { apiKey: process.env.DIAL_API_KEY! },
});
const account = await dial.account.get();
console.log(account.credits, account.authMethod);Scopes
Each key carries an allow-list. Privy dashboard sessions bypass scope checks; API keys do not.
| Scope | Routes |
|---|---|
| (any valid key) | GET /api/v1/account, GET /api/v1/account/credits |
account:read | GET /api/v1/account/usage, GET /api/v1/account/history, GET /api/v1/account/subscription |
sms:send | POST /api/v1/sms/send, POST /api/v1/messaging/send, POST /api/v1/numbers/mine/send |
numbers:buy | POST /api/v1/numbers/buy, /buy/us, /buy/intl, POST /api/v1/xmpp/provision, POST /api/v1/numbers/mine/renew |
numbers:read | GET /api/v1/numbers/mine, GET /api/v1/numbers/mine/messages, GET /api/v1/numbers/buy/status, GET /api/v1/sms/inbox, PUT /api/v1/numbers/mine/webhook, GET /api/v1/messaging/threads, GET /api/v1/messaging/threads/:counterparty |
lookup:read | POST /api/v1/lookup |
dehashed:search | POST /api/v1/dehashed/search, POST /api/v1/dehashed/search-with-credits |
esim:order | POST /api/v1/esim/checkout |
verifications:start | POST /api/v1/verifications/start |
Missing scope → 403 with { "error": "missing_scope", "required": "…" }.
Onboarding keys minted from the dashboard include account:read, sms:send,
numbers:read, and numbers:buy by default.
API keys vs Bearer (Privy) vs x402
| Use case | Pick |
|---|---|
| Browser / dashboard session | Privy bearer (auto-refreshed ~hourly) |
| Long-running bot, cron, partner backend | dial_live_* API key |
| One-off agent payment, no account | x402 per request |
Rotation (zero downtime)
- Mint a new key with the same scopes in
/dashboard/billing. - Deploy or update your
.envwith the new secret. - Revoke the old key from the dashboard.
- Confirm traffic stopped on the old prefix via audit logs.
Security
- Treat keys like passwords — never commit them to git.
- If leaked, revoke immediately and rotate.
- Keys cannot mint other keys (dashboard Privy session required for CRUD).