Connect your platform to KaiCalls
Get a referral code, connect your own workspace, and let providers activate a Kai phone line from your app. New providers verify their email without a card or an existing API key.
1. Get your partner code
Join the partner program with your name and email. The result gives you your referral code and link. Already registered? Use the email-only “Recover my links” form on that page. Your existing code and access link go to the registered email; recovery does not show the code in its browser response.
Your partner code attributes provider signups to you. It is not an API key and does not create a KaiCalls login or phone workspace. Use the code from the partner form, not a customer referral code from another dashboard.
referral_code: "YOUR_PARTNER_CODE"2. Connect your own workspace
Already have a KaiCalls account?
Sign in and select the business you intend to connect. An owner or admin can open Developer Platform with Partner integration selected, review the permissions, and create a key. A bearer key cannot mint or upgrade another key; key management uses your signed-in session.
Need an account?
Use the email verification flow below with your own business and email first, but omit referral_code for your own account: the partner program does not allow self-referrals. Only include your code when activating a referred provider. This creates a real workspace with the free browser preview; live phone service starts after payment. A partner registration does not include a separate sandbox or unlimited demo entitlement.
Save the key privately
Store the one-time key encrypted in your server secret manager and set runtime variables KAICALLS_API_KEY and KAICALLS_BUSINESS_ID. Keep them out of browser code, chat, commits, and logs. In Codex cloud, use Environment variables in an environment restricted to your authorized developers; the separate Secrets field is removed after setup, before the agent runs. Local Codex needs the variables in the environment that launches it.
The Partner integration permissions allow listing and agent configuration, webhook setup, and account reads. They do not include outbound calls, SMS sends, phone purchases, billing changes, or workspace lifecycle writes. Add further permissions only for an intended feature.
3. Activate each provider with their own email
Call POST https://www.kaicalls.com/api/v1/signup from your server with Content-Type: application/json and no Authorization header. Replace the example business and email with the provider's real details. Send the same referral code and permission set on both requests. The verification email discloses those permissions to the provider.
Send the verification code
{
"business_name": "Provider business name",
"email": "owner@example.com",
"activation_mode": "otp",
"referral_code": "YOUR_PARTNER_CODE",
"api_key_scopes": [
"workspaces:read",
"numbers:read",
"agents:read",
"agents:write",
"products:read",
"products:write",
"knowledge:read",
"knowledge:write",
"webhooks:read",
"webhooks:write",
"calls:read",
"billing:read"
]
}The response returns status: otp_sent, challenge_id, and expires_in_seconds. No account has been created yet. Ask the provider to enter the code from their own email.
Complete verification
{
"business_name": "Provider business name",
"email": "owner@example.com",
"activation_mode": "otp",
"referral_code": "YOUR_PARTNER_CODE",
"api_key_scopes": [
"workspaces:read",
"numbers:read",
"agents:read",
"agents:write",
"products:read",
"products:write",
"knowledge:read",
"knowledge:write",
"webhooks:read",
"webhooks:write",
"calls:read",
"billing:read"
],
"challenge_id": "RETURNED_CHALLENGE_ID",
"otp_code": "PROVIDER_EMAIL_CODE"
}Omitting api_key_scopes produces a read-only key. Changing or removing a requested set after the code was sent invalidates verification. Keep the other signup fields the same too. Explicit scope requests require OTP mode; payment mode rejects this field.
Store the returned api_key, business_id, agent_id, and phone_number against that provider in your system. Encrypt the key and sensitive password_setup_link or dashboard_magic_link; the key is returned once. Give account-access links only to the verified owner. Use each provider's key and business_id for their requests, rather than your own workspace key.
Respect 429 rate limits and code expiry. An email_exists response means the provider should sign in and connect their existing business through Developer Platform. Use error.recovery_paths for the returned sign-in and key-setup links.
4. Sync the listing and register a webhook
Read the authenticated OpenAPI contract and schema catalog with the provider key. The catalog includes signupOtpRequest, signupOtpVerify, productUpsert, knowledgeUpsert, agentCreate, agentUpdate, and webhookUpsert. Use /api/v1/schemas?name=productUpsert to fetch one schema. These URLs require your bearer header; the public OpenAPI YAML can be read before a key is available.
POST /api/v1/products
{
"business_id": "PROVIDER_BUSINESS_ID",
"name": "Lawn mowing",
"price": 75,
"description": "One lawn mowing visit",
"attributes": {
"duration_minutes": 60
}
}POST /api/v1/knowledge
{
"business_id": "PROVIDER_BUSINESS_ID",
"title": "Service area",
"content": "We serve Hoboken, NJ.",
"content_type": "text"
}Substitute real listing data. Save product.id and knowledge.id from the responses and include id on later POST updates. Knowledge updates also require business_id. Reusing a name, SKU, or title creates another record; it does not update the first one. Use agentUpdate to configure the existing returned agent rather than creating a second one.
POST /api/v1/webhooks
{
"business_id": "PROVIDER_BUSINESS_ID",
"webhook_url": "https://your-platform.example/api/kaicalls/webhook",
"events": [
"workspace.ready",
"phone_number.assigned",
"call.completed"
],
"is_active": true
}Use your real public HTTPS receiver and only supported events from capabilities or webhookUpsert. Store the signing secret when returned. Verify the signature over the raw request body before accepting a delivery and deduplicate event IDs. Follow the webhook signature reference.
5. Verify and recover without duplicate accounts
Using the runtime key, read GET /api/v1/capabilities, /api/v1/balance, and /api/v1/agents. Confirm the expected workspace, granted permissions, agent, and remaining allowance. Record HTTP status and non-secret IDs; never print the credential.
For an optional configuration test in your own workspace, create one clearly labeled product or knowledge record, read it back, update it by its returned id, then delete it and confirm removal. This checks writes without placing calls or sending messages. Keep automated tests mocked; only test live phone behavior with agreed, consenting test numbers.
HTTP 503 with status: provisioning_failed can still mean the account exists. Securely save the returned key and access links even on that response, inspect setup_status, and follow setup_status.recovery_paths to sign in, set up a key, or resume provisioning in the dashboard. Do not restart signup to get another account. A redacted replay response does not return the key again. If account access is unavailable, use account recovery or contact support with the returned business_id and setup_status.
KaiCalls has no sandbox keys. Your application's payment sandbox and mocked API tests are separate from live KaiCalls phone service. There is no general-purpose shared test key.
Download the agent onboarding skill