Skip to content

Phone & Voice API

AI-powered outbound voice calls (Bland.ai) and wallet-owned phone numbers (Twilio). Make conversational AI calls with real-time transcripts, buy/manage dedicated US/CA numbers, and perform carrier/fraud lookups. Outbound only, no SMS.

Base URL: https://api.jarvisclaw.ai/v1/marketplace/phone

Pricing

EndpointPriceDescription
POST /voice/call$0.54/callInitiate AI voice call
GET /voice/call/:call_idFreeRetrieve call status/transcript
POST /lookup$0.01/requestCarrier identification
POST /lookup/fraud$0.05/requestFraud risk assessment
POST /numbers/buy$5.00/numberLease a phone number (30-day)
POST /numbers/list$0.001/requestList owned numbers

Endpoints

POST /voice/call

Initiate an outbound AI voice call. The AI agent handles the conversation using the provided task/system prompt. Powered by Bland.ai.

Parameters

ParameterTypeRequiredDescription
tostringYesDestination phone number (E.164 format, e.g., +14155551234)
fromstringNoCaller ID — must be a leased number from /numbers/buy
taskstringYesInstructions for the AI voice agent (system prompt)
voicestringNoVoice preset. Default: nova
max_durationintegerNoMax call duration in seconds. Default: 1800 (30 min)
webhook_urlstringNoURL for real-time call status events
first_sentencestringNoOverride the AI's opening line
wait_for_greetingbooleanNoWait for callee to speak first. Default: true

Request Example

json
{
  "to": "+14155551234",
  "from": "+14155559876",
  "task": "You are an appointment reminder assistant. Confirm the user's dental appointment for Tuesday June 17 at 2 PM. Be polite and concise.",
  "voice": "nova",
  "max_duration": 120,
  "first_sentence": "Hi, this is a reminder call from Dr. Smith's office.",
  "wait_for_greeting": true
}

Response Example

json
{
  "call_id": "call_abc123def456",
  "status": "initiated",
  "to": "+14155551234",
  "from": "+14155559876",
  "created_at": "2025-06-13T12:00:00Z"
}

GET /voice/call/:call_id

Retrieve the full transcript, status, and metadata for a call.

Parameters

ParameterTypeRequiredDescription
call_idstringYesCall ID (path parameter)

Response Example

json
{
  "call_id": "call_abc123def456",
  "status": "completed",
  "duration_seconds": 45,
  "to": "+14155551234",
  "from": "+14155559876",
  "transcript": [
    {"role": "assistant", "content": "Hi, this is a reminder call from Dr. Smith's office."},
    {"role": "user", "content": "Yes, hello?"},
    {"role": "assistant", "content": "I'm calling to confirm your dental appointment for Tuesday June 17 at 2 PM. Can you confirm you'll be there?"},
    {"role": "user", "content": "Yes, I'll be there. Thank you."},
    {"role": "assistant", "content": "Great, you're all set. Have a wonderful day!"}
  ],
  "summary": "User confirmed dental appointment for Tuesday June 17 at 2 PM.",
  "created_at": "2025-06-13T12:00:00Z",
  "ended_at": "2025-06-13T12:00:45Z"
}

Call statuses: initiated, ringing, in_progress, completed, failed, no_answer, busy


POST /lookup

Identify the carrier and line type for a phone number.

Parameters

ParameterTypeRequiredDescription
phoneNumberstringYesPhone number in E.164 format

Request Example

json
{
  "phoneNumber": "+14155551234"
}

Response Example

json
{
  "phoneNumber": "+14155551234",
  "carrier": "T-Mobile",
  "line_type": "mobile",
  "country": "US",
  "country_code": "1"
}

POST /lookup/fraud

Assess fraud risk and identify suspicious indicators for a phone number.

Parameters

ParameterTypeRequiredDescription
phoneNumberstringYesPhone number in E.164 format

Request Example

json
{
  "phoneNumber": "+14155551234"
}

Response Example

json
{
  "phoneNumber": "+14155551234",
  "risk_score": 15,
  "risk_level": "low",
  "flags": [],
  "carrier": "T-Mobile",
  "line_type": "mobile",
  "is_voip": false,
  "is_prepaid": false
}

Risk levels: low (0-25), medium (26-50), high (51-75), critical (76-100)


POST /numbers/buy

Lease a dedicated phone number for use as a caller ID on outbound calls.

Parameters

ParameterTypeRequiredDescription
countrystringYesISO country code (US or CA)
area_codestringNoPreferred area code (e.g., 415)

Request Example

json
{
  "country": "US",
  "area_code": "415"
}

Response Example

json
{
  "number": "+14155559876",
  "country": "US",
  "capabilities": ["voice"],
  "monthly_cost": 5.00,
  "lease_start": "2025-06-13T12:00:00Z",
  "expires_at": "2025-07-13T12:00:00Z"
}

POST /numbers/list

List all phone numbers currently leased to your account.

Request Example

json
{}

Response Example

json
{
  "numbers": [
    {
      "number": "+14155559876",
      "country": "US",
      "capabilities": ["voice"],
      "monthly_cost": 5.00,
      "lease_start": "2025-06-01T12:00:00Z",
      "expires_at": "2025-07-01T12:00:00Z",
      "status": "active"
    }
  ],
  "total": 1
}

Errors

HTTP CodeError CodeDescription
400invalid_phone_numberPhone number is not valid E.164 format
404number_not_ownedThe from number is not leased to your account
404call_not_foundNo call found with the specified call_id
409number_unavailableRequested number or area code has no availability
500call_failedVoice call could not be connected (carrier/network issue)

Error Response Format

json
{
  "error": {
    "code": "invalid_phone_number",
    "message": "The phone number '+1415555' is not valid E.164 format. Expected format: +14155551234"
  }
}

Code Examples

bash
# Initiate a voice call
curl -X POST https://api.jarvisclaw.ai/v1/marketplace/phone/voice/call \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155551234",
    "task": "You are a friendly appointment reminder. Confirm the dental appointment for Tuesday at 2 PM.",
    "voice": "nova",
    "max_duration": 120
  }'

# Get call transcript
curl https://api.jarvisclaw.ai/v1/marketplace/phone/voice/call/call_abc123def456 \
  -H "Authorization: Bearer sk-your-api-key"

# Carrier lookup
curl -X POST https://api.jarvisclaw.ai/v1/marketplace/phone/lookup \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"phoneNumber": "+14155551234"}'

# Fraud risk check
curl -X POST https://api.jarvisclaw.ai/v1/marketplace/phone/lookup/fraud \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"phoneNumber": "+14155551234"}'

# Buy a phone number
curl -X POST https://api.jarvisclaw.ai/v1/marketplace/phone/numbers/buy \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"country": "US", "area_code": "415"}'

# List owned numbers
curl -X POST https://api.jarvisclaw.ai/v1/marketplace/phone/numbers/list \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{}'
python
import requests

BASE = "https://api.jarvisclaw.ai/v1/marketplace/phone"
HEADERS = {
    "Authorization": "Bearer sk-your-api-key",
    "Content-Type": "application/json",
}

# Initiate an AI voice call
resp = requests.post(f"{BASE}/voice/call", headers=HEADERS, json={
    "to": "+14155551234",
    "task": "You are an appointment reminder assistant. Confirm the dental appointment for Tuesday at 2 PM.",
    "voice": "nova",
    "max_duration": 120,
})
call = resp.json()
print(f"Call initiated: {call['call_id']}")

# Get transcript after call completes
resp = requests.get(
    f"{BASE}/voice/call/{call['call_id']}",
    headers={"Authorization": "Bearer sk-your-api-key"},
)
transcript = resp.json()
print(f"Status: {transcript['status']}, Duration: {transcript['duration_seconds']}s")
for turn in transcript["transcript"]:
    print(f"  {turn['role']}: {turn['content']}")

# Carrier lookup
resp = requests.post(f"{BASE}/lookup", headers=HEADERS, json={
    "phoneNumber": "+14155551234",
})
info = resp.json()
print(f"Carrier: {info['carrier']}, Type: {info['line_type']}")

# Fraud risk assessment
resp = requests.post(f"{BASE}/lookup/fraud", headers=HEADERS, json={
    "phoneNumber": "+14155551234",
})
risk = resp.json()
print(f"Risk: {risk['risk_level']} (score: {risk['risk_score']})")

# Buy a number
resp = requests.post(f"{BASE}/numbers/buy", headers=HEADERS, json={
    "country": "US",
    "area_code": "415",
})
print(f"Leased: {resp.json()['number']}")

# List owned numbers
resp = requests.post(f"{BASE}/numbers/list", headers=HEADERS, json={})
for num in resp.json()["numbers"]:
    print(f"  {num['number']} — expires {num['expires_at']}")
python
from jarvisclaw import PhoneClient

# x402 Agent wallet — pays per-call via USDC
# Base chain (EVM)
phone = PhoneClient(private_key="0x<evm-private-key>")

# Or Solana
# phone = PhoneClient(private_key="<solana-bs58-keypair>")

# Initiate an AI voice call
call = phone.voice_call(
    to="+14155551234",
    task="You are an appointment reminder assistant. Confirm the dental appointment for Tuesday at 2 PM.",
    voice="nova",
    max_duration=120,
)
print(f"Call initiated: {call.call_id}")

# Get transcript
transcript = phone.get_call(call.call_id)
print(f"Status: {transcript.status}, Duration: {transcript.duration_seconds}s")
for turn in transcript.transcript:
    print(f"  {turn['role']}: {turn['content']}")

# Carrier lookup
info = phone.lookup("+14155551234")
print(f"Carrier: {info.carrier}, Type: {info.line_type}")

# Fraud risk assessment
risk = phone.lookup_fraud("+14155551234")
print(f"Risk: {risk.risk_level} (score: {risk.risk_score})")

# Buy a number
number = phone.buy_number(country="US", area_code="415")
print(f"Leased: {number.number}")

# List owned numbers
numbers = phone.list_numbers()
for num in numbers:
    print(f"  {num.number} — expires {num.expires_at}")
go
package main

import (
    "context"
    "fmt"
    jc "github.com/api-jarvisclaw/go-sdk"
)

func main() {
    ctx := context.Background()
    phone, _ := jc.NewPhoneClient(jc.WithAPIKey("sk-your-api-key"))

    // Initiate an AI voice call
    call, _ := phone.VoiceCall(ctx, &jc.VoiceCallRequest{
        To:          "+14155551234",
        Task:        "You are an appointment reminder. Confirm dental appointment Tuesday at 2 PM.",
        Voice:       "nova",
        MaxDuration: 120,
    })
    fmt.Printf("Call initiated: %s\n", call.CallID)

    // Get transcript
    transcript, _ := phone.GetCall(ctx, call.CallID)
    fmt.Printf("Status: %s, Duration: %ds\n", transcript.Status, transcript.DurationSeconds)
    for _, turn := range transcript.Transcript {
        fmt.Printf("  %s: %s\n", turn.Role, turn.Content)
    }

    // Carrier lookup
    info, _ := phone.Lookup(ctx, "+14155551234")
    fmt.Printf("Carrier: %s, Type: %s\n", info.Carrier, info.LineType)

    // Fraud risk assessment
    risk, _ := phone.LookupFraud(ctx, "+14155551234")
    fmt.Printf("Risk: %s (score: %d)\n", risk.RiskLevel, risk.RiskScore)

    // Buy a number
    number, _ := phone.BuyNumber(ctx, &jc.BuyNumberRequest{
        Country:  "US",
        AreaCode: "415",
    })
    fmt.Printf("Leased: %s\n", number.Number)

    // List owned numbers
    numbers, _ := phone.ListNumbers(ctx)
    for _, num := range numbers {
        fmt.Printf("  %s — expires %s\n", num.Number, num.ExpiresAt)
    }
}
go
package main

import (
    "context"
    "fmt"
    jc "github.com/api-jarvisclaw/go-sdk"
)

func main() {
    ctx := context.Background()

    // x402 Agent wallet — pays per-call via USDC on Base
    phone, _ := jc.NewPhoneClient(jc.WithPrivateKey("0x<evm-private-key>"))

    // Initiate an AI voice call
    call, _ := phone.VoiceCall(ctx, &jc.VoiceCallRequest{
        To:          "+14155551234",
        Task:        "You are an appointment reminder. Confirm dental appointment Tuesday at 2 PM.",
        Voice:       "nova",
        MaxDuration: 120,
    })
    fmt.Printf("Call initiated: %s\n", call.CallID)

    // Get transcript
    transcript, _ := phone.GetCall(ctx, call.CallID)
    fmt.Printf("Status: %s, Duration: %ds\n", transcript.Status, transcript.DurationSeconds)

    // Carrier lookup
    info, _ := phone.Lookup(ctx, "+14155551234")
    fmt.Printf("Carrier: %s, Type: %s\n", info.Carrier, info.LineType)

    // Fraud risk assessment
    risk, _ := phone.LookupFraud(ctx, "+14155551234")
    fmt.Printf("Risk: %s (score: %d)\n", risk.RiskLevel, risk.RiskScore)

    // Buy a number
    number, _ := phone.BuyNumber(ctx, &jc.BuyNumberRequest{
        Country:  "US",
        AreaCode: "415",
    })
    fmt.Printf("Leased: %s\n", number.Number)
}

Limitations

  • Outbound only — inbound call handling and receiving calls is not supported
  • No SMS — phone numbers are voice-only, SMS is not available
  • 30-minute max call duration — calls are automatically terminated at 1800 seconds
  • US/CA default — numbers outside US and Canada require KYC verification
  • English only — voice AI currently supports English language conversations only
  • 30-day lease — phone numbers auto-renew monthly unless cancelled
  • E.164 format required — all phone numbers must include country code (e.g., +14155551234)
  • Caller ID — the from field must be a number you've leased, or it will be omitted (calls show as unknown)

Pay per call. No subscription. No rate limits.