Bearer Token (Credits Auth)
Where the Bearer token comes from, how to grab one from the dashboard, and how to use it on credits-mode API endpoints.
Bearer Token (Credits Auth)
The Authorization: Bearer … header on credits-mode endpoints carries a
Privy access token — the same JWT the dashboard uses to authenticate
your session. There is no separate signup, no API console, no manual key
issuance: if you can sign in to the dashboard, you can mint one.
If you would rather pay per request without an account at all, skip this page and use x402 — every credits-mode endpoint also works with x402 and a USDC-funded wallet.
When to use Bearer (vs x402)
| You want… | Use |
|---|---|
| Pre-buy credits, then run scripts without re-signing each call | Bearer |
| Stay account-less; pay per request from a funded wallet | x402 |
| Mix and match (script with credits, agent with wallet) | Either — every paid endpoint supports both |
Internally the API resolves auth in this order (see
apps/web/lib/dual-payment.ts):
Authorization: Bearer <privy-access-token>→ debit credits.- No Bearer token → fall through to x402 (signed
PAYMENT-SIGNATURE). Authorization: Bearer <DIAL_ADMIN_API_KEY>→ operator bypass (no payment).
Get a token from the dashboard (recommended)
- Open
/dashboard/billingand sign in with Privy (email, wallet, or social — same provider as everywhere else). - Find the API Token card.
- Click Reveal token → click Copy.
- Paste it into your shell or script as
Authorization: Bearer <token>.
The token rotates every ~1 hour. The dashboard auto-refreshes silently while it is open, but anything pasted into a long-running script will need to be re-fetched after expiry. Click Refresh in the API Token card to mint a fresh one.
Get a token programmatically
If your app is already using the Privy SDK on
the same app.id as Dial, call getAccessToken():
import { usePrivy } from "@privy-io/react-auth";
function MyComponent() {
const { getAccessToken } = usePrivy();
const send = async () => {
const token = await getAccessToken();
if (!token) throw new Error("Sign in first");
await fetch("https://x402.dial.wtf/api/v1/sms/send", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ to: "+18148835337", message: "hi from credits" }),
});
};
}Server-side, you can verify a Privy token with @privy-io/server-auth
the same way Dial does internally — but that's only useful if you're
proxying / caching Dial calls behind your own service.
Use the token
Once you have a token, every credits-mode endpoint accepts it:
TOKEN="<paste-from-dashboard>"
curl -sS -X POST "https://x402.dial.wtf/api/v1/sms/send" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"to":"+18148835337","message":"Hello via credits"}'Sample success response:
{
"success": true,
"provider": "dial",
"messageId": "msg_…",
"to": "+18148835337",
"segments": 1
}If you have no credits left, you'll see:
{
"success": false,
"error": "insufficient_credits",
"credits": 0,
"required": 1
}(HTTP 402.) Top up via the dashboard or call
/api/v1/credits/top-up once with x402
to refill, then keep using the same Bearer token.
Check your balance
curl -sS "https://x402.dial.wtf/api/v1/account" \
-H "Authorization: Bearer $TOKEN"{
"credits": 9384,
"privyUserId": "did:privy:cm…"
}Lifetime, refresh, revocation
- TTL: ~1 hour (set by Privy; not configurable per-app).
- Refresh: the dashboard auto-refreshes via the Privy SDK while open.
Headless callers must call
getAccessToken()(or click Refresh in the dashboard card) again after expiry. - Revocation: signing out of Privy invalidates the current token and every script using it. There is no per-token revoke today — that is tracked in #12 along with long-lived programmatic API keys.
Security checklist
- Treat the token like a password. Anyone with the string can spend your credits until it expires.
- Do not commit it to source control or paste it into chat threads.
- Prefer
getAccessToken()over hard-coding tokens — the SDK refresh loop is the only thing that survives a redeploy without manual intervention. - For server-to-server agents that need a stable identity, watch #12 or use x402 signed payments instead.
See also
- Getting Started — pick between Bearer and x402.
/api/v1/credits/top-up— buy credits with x402./api/v1/account— verify your balance.
API Reference
Complete REST API reference for all Dial x402 endpoints.
Buy Phone Line POST
Buy an exclusive phone line — no KYC required. $100 activation includes the first month and 10,000 free texts. Renews at $60/mo with 5,000 free texts per month. Full send and receive SMS. Manage from the dashboard with a Privy session.