Skip to navigation

API quickstart

This walkthrough creates a US SMS/voice number and verifies an inbound text. Use your own mobile phone for the test. For iMessage, follow Set up iMessage instead.

Before you start

You need an AgentPhone account, an API key from Settings, curl, and jq.

New accounts receive $5 in credit. A standard US/Canadian number costs $3 for its first month, charged when provisioned, and usage also draws from the balance. See Billing for other number types and account-specific rates.

Inbound SMS does not require 10DLC registration. Outbound SMS needs registration and number activation. Outbound phone calls require the account to satisfy the paid-access check; if you receive 402, follow its message and add funds in Billing. Signup credit alone does not unlock outbound calling.

export AGENTPHONE_API_KEY="YOUR_API_KEY"
export AGENTPHONE_BASE_URL="https://api.agentphone.ai"

These commands target your main account. If using a sub-account, add X-Sub-Account-Id consistently to each command; see Authentication.

1. Create an agent

Use hosted mode for a voice assistant that can answer calls without a voice webhook. Text replies will still be handled by your application.

AGENT_ID=$(curl --fail-with-body --silent --show-error \
"$AGENTPHONE_BASE_URL/v1/agents" \
-H "Authorization: Bearer $AGENTPHONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Support Bot","voiceMode":"hosted","systemPrompt":"You are a helpful support assistant.","beginMessage":"Hello! How can I help?"}' | jq -er '.id')

Save the returned ID. If the command fails, fix the reported error before continuing.

2. Buy and attach a number

This command charges the first month’s number fee. agentId attaches the new number in the same request.

NUMBER_JSON=$(curl --fail-with-body --silent --show-error \
"$AGENTPHONE_BASE_URL/v1/numbers" \
-H "Authorization: Bearer $AGENTPHONE_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg agentId "$AGENT_ID" '{country:"US",agentId:$agentId}')")
NUMBER_ID=$(printf '%s' "$NUMBER_JSON" | jq -er '.id')
printf '%s' "$NUMBER_JSON" | jq '{id, phoneNumber, agentId, outboundSms}'

Keep both id (used in API paths) and phoneNumber (the address people text or call). If you already own a number, attach it with POST /v1/agents/{agent_id}/numbers instead of buying another.

3. Receive a text

Text the returned phoneNumber from your mobile, then fetch its messages:

curl --fail-with-body "$AGENTPHONE_BASE_URL/v1/numbers/$NUMBER_ID/messages?limit=10" \
-H "Authorization: Bearer $AGENTPHONE_API_KEY"

Look for your text in data, with direction: "inbound". If it is missing, check that you used the right phone number and account scope. This proves inbound messaging before you add webhook processing.

4. Connect a webhook

Run a signed webhook handler on a public HTTPS URL. For local development, follow Testing.

curl --fail-with-body "$AGENTPHONE_BASE_URL/v1/webhooks" \
-H "Authorization: Bearer $AGENTPHONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://your-server.example/webhook","contextLimit":10}'

Save the response’s secret as AGENTPHONE_WEBHOOK_SECRET on your server, then restart the handler. Each save can change this secret.

curl --fail-with-body -X POST "$AGENTPHONE_BASE_URL/v1/webhooks/test" \
-H "Authorization: Bearer $AGENTPHONE_API_KEY"

Check for success: true and a 2xx httpStatus. Your handler receives a signed synthetic agent.message with test: true; it should acknowledge the event without sending a text. This tests delivery to your server, not carrier delivery or voice responses. Send another real inbound text to verify the full messaging path.

5. Send a reply when SMS is enabled

Check GET /v1/numbers/{number_id}. Wait for outboundSms: "enabled"; registration_required needs registration, and activating needs carrier attachment to finish.

Set the recipient to your own mobile number in E.164 format:

export TEST_RECIPIENT="+14155550123"
curl --fail-with-body "$AGENTPHONE_BASE_URL/v1/messages" \
-H "Authorization: Bearer $AGENTPHONE_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg numberId "$NUMBER_ID" --arg to "$TEST_RECIPIENT" \
'{number_id:$numberId,to_number:$to,body:"Hello from my AgentPhone integration."}')"

A successful send is acceptance, not proof of delivery. Read message history for status and failureReason. A timeout or DELIVERY_UNCONFIRMED can mean the send already happened; check the outcome before resending.

Returning {"text":"…"} to a text webhook does not send this reply. Your backend must call POST /v1/messages. Voice webhooks have a separate synchronous response contract.

Next steps and cleanup

  • Messages: media, reactions, groups, and conversation state.
  • Calls: hosted voice, custom voice webhooks, and browser calls.
  • Troubleshooting: registration, delivery, account scope, and billing problems.

Numbers renew until released. If you no longer need the test number, release it from Numbers in the dashboard or with DELETE /v1/numbers/{number_id}. Release is irreversible; deleting the agent alone does not release its numbers or stop their fees.