Programmatic signup — live in production

Connect Your Agent

This isn't a waitlist. POST /api/v1/signup is a real endpoint an AI agent can call right now — unauthenticated, no human in the loop required. Send the request, get a 402 with payment requirements, pay in USDC on Base, retry, and you're provisioned: API key, phone number, and a live agent, in one round trip. It's $5, instant, with a 7-day trial — or skip crypto at kaicalls.com.

Sign up without cryptoRead the docs

The endpoint

POST https://www.kaicalls.com/api/v1/signup — not /mcp. It's a separate REST endpoint that sits next to the MCP server, purpose-built for machine-initiated signup rather than tool calls against an existing account. The body:

business_namestring, required
emailstring, required — must contain "@"
business_typestring, optional
websitestring, optional
phone_forward_tostring, optional — the owner's cell; if set, ring-first routing is configured automatically
plan_idstring, optional — defaults to starter

It's rate-limited to 5 requests per hour per IP. Send a request with no payment header and here's exactly what you get back:

1. Request without payment → 402

POST /api/v1/signup HTTP/1.1
Host: www.kaicalls.com
Content-Type: application/json

{
  "business_name": "Acme Legal",
  "email": "owner@acmelegal.com",
  "business_type": "law_firm",
  "phone_forward_to": "+15551234567"
}

Copy-paste to try it yourself — this is the safe, no-payment request; it 402s by design and creates nothing:

curl -X POST https://www.kaicalls.com/api/v1/signup \
  -H "Content-Type: application/json" \
  -d '{
    "business_name": "Acme Legal",
    "email": "owner@acmelegal.com",
    "business_type": "law_firm",
    "phone_forward_to": "+15551234567"
  }'
HTTP/1.1 402 Payment Required
Content-Type: application/json
X-Payment-Required: <base64(requirements JSON below)>
X-Payment-Challenge: pi_3P...

{
  "error": {
    "code": "payment_required",
    "message": "Payment required to create account"
  },
  "x402": {
    "scheme": "exact",
    "network": "eip155:8453",
    "maxAmountRequired": "5000000",
    "resource": "/api/v1/signup",
    "description": "KaiCalls signup — AI phone agent provisioning",
    "mimeType": "application/json",
    "payTo": "0x...(Stripe-issued deposit address, fresh per request)",
    "maxTimeoutSeconds": 60,
    "asset": "eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "extra": {
      "provider": "stripe",
      "stripePaymentIntentId": "pi_3P...",
      "supportedTokens": ["..."]
    }
  },
  "payment_challenge_id": "pi_3P..."
}

Verified live against production today: network is eip155:8453 — Base mainnet — and asset is the USDC contract on Base. maxAmountRequired is USDC in 6-decimal base units; "5000000" is $5.00. The facilitator is Stripe Machine Payments — Stripe mints a fresh crypto deposit address (payTo) and a PaymentIntent (stripePaymentIntentId, echoed as X-Payment-Challenge and payment_challenge_id) per request, then settles the on-chain transfer against it once you pay.

2. Sign the transfer and retry

Send maxAmountRequired units of asset (5 USDC on Base) to payTo, then retry the identical request with two headers added: the signed payment as PAYMENT-SIGNATURE, and the challenge id you were issued echoed back as X-Payment-Challenge (a Payment-Intent header works too — the server checks either name).

POST /api/v1/signup HTTP/1.1
Host: www.kaicalls.com
Content-Type: application/json
PAYMENT-SIGNATURE: <your signed USDC transfer>
X-Payment-Challenge: pi_3P...

{
  "business_name": "Acme Legal",
  "email": "owner@acmelegal.com",
  "business_type": "law_firm",
  "phone_forward_to": "+15551234567"
}

The server verifies and settles the deposit via Stripe before doing anything else. If settlement fails, you get another 402 — { "error": { "code": "payment_invalid" } } — with no account created. If it succeeds:

3. Provisioned — response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "api_key": "kc_live_...",
  "business_id": "8f2a1c40-...",
  "agent_id": "3d9e7b10-...",
  "phone_number": "+15557890000",
  "dashboard_url": "https://www.kaicalls.com/dashboard",
  "trial_ends_at": "2026-07-16T04:12:00.000Z",
  "provisioning_deferred": false,
  "payment_capture": "x402",
  "dashboard_magic_link": "https://www.kaicalls.com/auth/callback?..."
}

Because the request was x402-verified, provisioning happened inline in the same call —agent_id and phone_number come back populated, not null. A real AI agent is live on a real Twilio number attached to a real Vapi assistant before the HTTP response even returns. Auth is the returned api_key as a bearer token on every subsequent call; dashboard_magic_link is a one-time login link if a human wants to look at the dashboard instead.

Honest fallback note: what happens without x402

The endpoint's code supports a non-x402 path — send the request, skip payment entirely, and get back provisioning_deferred: true with a checkout_url for Stripe Checkout, so a human completes card capture and the agent + phone number get provisioned afterward by the checkout.session.completed webhook instead of inline. That path only runs when x402 is turned off at the environment level, though. As verified against production today, x402 is enabledpayment.x402.enabled: true on the live agent.json discovery doc — which means every unauthenticated request to this endpoint hits the 402 gate first; there is currently no way to skip straight to a checkout link from this specific API route. If you'd rather not transact in USDC, the human path is the normal dashboard signup at kaicalls.com, which collects a card via Stripe Checkout and never touches x402 at all — it just isn't this endpoint.

Other things worth knowing

Demo-number conversion

If phone matches a number already talking to a KaiCalls demo instance, signup converts that demo business into a real trialing account and links it to the new user, instead of creating a duplicate.

Duplicate email

An email that's already registered returns 409 with { "error": { "code": "email_exists" } } — retry with a different email or authenticate normally instead of retrying the same payload.

7-day trial either way

Both paths start a 7-day trial (trial_ends_at). The x402 path skips the card-capture step at signup time; a subscription still governs ongoing billing after the trial.

Ring-first routing

Passing phone_forward_to on an x402-verified signup configures ring-first routing automatically — calls try the owner's cell before falling back to the AI agent — with no separate config call needed.

Sign up without cryptoRead the docsSafety & compliance
Connect