Pine Voice/Pine Voice API Reference
Pine Voice — Direct CallDeveloper Preview

Pine Voice API Reference

Integrate Pine voice calls directly into your application using the REST API or SDK. This API is for direct voice calls. For broader Pine Assistant sessions and tasks, use the Assistant API instead.

Back to Voice

Base URLs

The API uses two hosts. Authentication goes through the Pine main API; voice call endpoints go through the gateway.

Auth APIhttps://www.19pine.ai
Voice APIhttps://agent3-api-gateway-staging.19pine.ai

All endpoints accept and return JSON. Include Content-Type: application/json in all requests.

Authentication

Pine Voice uses a two-step email verification flow to issue access tokens. Tokens are then passed as Bearer tokens in subsequent API calls.

Authentication flow

1

Request a verification code

Send your Pine account email to receive a one-time verification code via email.

2

Verify the code

Submit the code from your email along with the request_token. You get back an access_token and user_id.

3

Use credentials in API calls

Include both the access token and user ID as headers in all voice requests.

Required headers

HTTP headers
Authorization: Bearer <access_token>
X-Pine-User-Id: <user_id>
Content-Type: application/json
Prerequisite: You need an active Pine subscription and a registered phone number on your Pine account.

Request Verification Code

POST/api/v2/auth/email/request

Sends a one-time verification code to the provided email address. The email must be associated with an existing Pine account.

Request body

ParameterTypeDescription
emailstringYour Pine account email address

Example request

cURL
curl -X POST https://www.19pine.ai/api/v2/auth/email/request \
  -H "Content-Type: application/json" \
  -d '{
    "email": "you@example.com"
  }'

Success response

JSON
{
  "status": "success",
  "data": {
    "request_token": "eyJhbGciOiJIUzI1NiIs..."
  }
}

Verify Code & Get Token

POST/api/v2/auth/email/verify

Verifies the one-time code from your email and returns your access credentials. Store both access_token and id securely.

Request body

ParameterTypeDescription
emailstringSame email used in the request step
request_tokenstringThe request_token from the previous step
codestringThe verification code received via email

Example request

cURL
curl -X POST https://www.19pine.ai/api/v2/auth/email/verify \
  -H "Content-Type: application/json" \
  -d '{
    "email": "you@example.com",
    "request_token": "REQUEST_TOKEN",
    "code": "1234"
  }'

Success response

JSON
{
  "status": "success",
  "data": {
    "id": "1234567890",
    "access_token": "eyJhbGciOiJSUzI1NiIs..."
  }
}
Security: Store your access_token securely. Do not commit it to version control or log it in plaintext.

Initiate a Phone Call

POST/api/v2/voice/call

Validates your request, runs safety and billing checks, and initiates a phone call using Pine's AI voice agent. The request blocks while the call is being set up, then returns a call_id.

Async results. Use the SSE stream endpoint to wait for the final transcript, or poll the GET endpoint periodically. No intermediate live updates are emitted during the call.

Request body

ParameterTypeDescription
dialed_numberstringPhone number to call in E.164 format, for example +14155551234.
callee_namestringName of the person or business being called.
callee_contextstringBackground context about the callee.
call_objectivestringClear, specific goal for the call.
detailed_instructionsstringOptional strategy, constraints, or fallback logic.
caller"negotiator" | "communicator"Optional. Defaults to negotiator.
voice"male" | "female"Optional. Defaults to female.
max_duration_minutesintegerOptional. 1 to 120 minutes. Defaults to 120.
enable_summarybooleanOptional. Request an LLM-generated summary after completion.

Example request

cURL
curl -X POST https://agent3-api-gateway-staging.19pine.ai/api/v2/voice/call \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Pine-User-Id: YOUR_USER_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "dialed_number": "+14155551234",
    "callee_name": "Dr. Smith Office",
    "callee_context": "Local dentist office, open Mon-Fri 9am-5pm",
    "call_objective": "Schedule a dental cleaning appointment for next Tuesday afternoon",
    "caller": "communicator",
    "voice": "female",
    "max_duration_minutes": 10
  }'

Success response

JSON
{
  "call_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "in_progress"
}

Caller Types: Negotiator vs Communicator

The caller parameter selects which Pine voice agent handles the call. Choosing the right type and providing the right level of detail is critical to call success.

Negotiator

Best for bill reductions, disputes, retention saves, contract renegotiations, and any call where the agent must defend a target outcome.

  • Include target outcome, acceptable range, leverage points, and constraints.
  • Good fit for adversarial or persuasive calls.
  • Under-specified strategy usually produces poor results.

Communicator

Best for scheduling, reservations, confirmations, information requests, and straightforward operational calls.

  • Provide context, preferences, and fallback options.
  • Usually the right default for product workflows and testing.
  • No hard negotiation strategy required.
Negotiation calls require strategy details. If you use negotiator, all strategy must be provided upfront in callee_context and detailed_instructions.

Example: Negotiator call

JSON — negotiator request body
{
  "dialed_number": "+18005551234",
  "callee_name": "Internet Provider Support",
  "callee_context": "Current plan: 200 Mbps at $89.99/mo. Competitor offer: same speed at $49.99/mo.",
  "call_objective": "Negotiate the monthly bill down from $89.99 to $60/mo or less",
  "detailed_instructions": "Target: $60/mo. Acceptable range: up to $65/mo. Mention competitor offer as leverage. Do not change plan tier.",
  "caller": "negotiator",
  "voice": "male",
  "max_duration_minutes": 30
}

Example: Communicator call

JSON — communicator request body
{
  "dialed_number": "+14155559876",
  "callee_name": "The Italian Place",
  "callee_context": "Italian restaurant on Main Street. Making a reservation for dinner.",
  "call_objective": "Make a dinner reservation for 4 people tonight at 7pm",
  "detailed_instructions": "If 7pm is not available, try 7:30 or 8pm. Prefer a booth if possible.",
  "caller": "communicator",
  "voice": "female",
  "max_duration_minutes": 10
}

Get Call Status

GET/api/v2/voice/call/{call_id}

Poll this endpoint periodically until the call completes, or use SSE to wait for the final result instead. Once the call completes, the response includes the full transcript and optional summary.

Path parameters

ParameterTypeDescription
call_idstringThe call_id returned from the initiate call endpoint

Example request

cURL
curl https://agent3-api-gateway-staging.19pine.ai/api/v2/voice/call/CALL_ID \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Pine-User-Id: YOUR_USER_ID"

Response fields

FieldTypeDescription
call_idstringUnique identifier for the call.
statusstringOne of "in_progress", "completed", "failed", or "cancelled".
duration_secondsnumberElapsed duration while running and after completion.
summarystringOptional final summary when requested.
transcriptarrayFull transcript after the call reaches a terminal state.
credits_chargednumberCredits billed for the completed call.

Stream Call Status (SSE)

GET/api/v2/voice/call/{call_id}/stream

Opens a Server-Sent Events stream that waits for the final call result and delivers it as soon as it's available. This is the recommended alternative to polling.

No real-time updates. The SSE stream emits only the final result event after the call ends. It does not stream partial transcripts or live state changes.
SSE
curl -N https://agent3-api-gateway-staging.19pine.ai/api/v2/voice/call/CALL_ID/stream \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Pine-User-Id: YOUR_USER_ID" \
  -H "Accept: text/event-stream"

Quickstart

The easiest way to integrate Pine Voice is with the official SDKs. They handle authentication, request formatting, SSE result delivery with automatic polling fallback, and error handling for you.

Python

Sync and async support. Python 3.9+.

Python quickstart
from pine_voice import PineVoice

request_token = PineVoice.auth.request_code("you@example.com")
credentials = PineVoice.auth.verify_code("you@example.com", request_token, "1234")

client = PineVoice(
    access_token=credentials.access_token,
    user_id=credentials.user_id,
)

result = client.calls.create_and_wait(
    to="+14155551234",
    name="Dr. Smith Office",
    context="Local dentist office. Open Mon-Fri 9am-5pm.",
    objective="Schedule a dental cleaning for next Tuesday afternoon",
    caller="communicator",
)

print(result.status)
print(result.transcript)

Node.js / TypeScript

Minimal setup for JS products and edge runtimes.

TypeScript quickstart
import { PineVoice } from "pine-voice";

const { requestToken } = await PineVoice.auth.requestCode("you@example.com");
const { accessToken, userId } = await PineVoice.auth.verifyCode(
  "you@example.com",
  requestToken,
  "1234",
);

const client = new PineVoice({ accessToken, userId });

const result = await client.calls.createAndWait({
  to: "+14155551234",
  name: "Dr. Smith Office",
  context: "Local dentist office. Open Mon-Fri 9am-5pm.",
  objective: "Schedule a dental cleaning for next Tuesday afternoon",
  caller: "communicator",
});

console.log(result.status);
console.log(result.transcript);

Python SDK Reference

Full API reference for the pine-voice Python package. Supports both synchronous and asynchronous usage.

Constructor

ArgumentTypeDescription
access_tokenstrRequired. Bearer token from the auth flow.
user_idstrRequired. Pine user ID used as X-Pine-User-Id.
gateway_urlstrOptional. Defaults to the staging gateway URL.

Authentication

Python auth
from pine_voice import PineVoice

request_token = PineVoice.auth.request_code("you@example.com")
credentials = PineVoice.auth.verify_code("you@example.com", request_token, "1234")

calls.create_and_wait()

Initiates a call and blocks until it reaches a terminal state. Uses SSE first, with automatic polling fallback if streaming fails.

Python
from pine_voice import PineVoice

request_token = PineVoice.auth.request_code("you@example.com")
credentials = PineVoice.auth.verify_code("you@example.com", request_token, "1234")

client = PineVoice(
    access_token=credentials.access_token,
    user_id=credentials.user_id,
)

result = client.calls.create_and_wait(
    to="+14155551234",
    name="Dr. Smith Office",
    context="Local dentist office. Open Mon-Fri 9am-5pm.",
    objective="Schedule a dental cleaning for next Tuesday afternoon",
    caller="communicator",
)

print(result.status)
print(result.transcript)

Errors

Error classWhen
PineVoiceErrorBase class for all SDK errors.
AuthErrorAuthentication failures, missing credentials, expired tokens.
CallErrorCall-specific failures such as invalid phone or policy rejection.
RateLimitErrorRate limit exceeded (429).

Node.js / TypeScript SDK Reference

All core types are exported from pine-voice and available for import in TypeScript.

Constructor

ArgumentTypeDescription
accessTokenstringRequired. Bearer token from the auth flow.
userIdstringRequired. Pine user ID used as X-Pine-User-Id.
gatewayUrlstringOptional. Defaults to the staging gateway URL.

Authentication

TypeScript auth
import { PineVoice } from "pine-voice";

const { requestToken } = await PineVoice.auth.requestCode("you@example.com");
const { accessToken, userId } = await PineVoice.auth.verifyCode("you@example.com", requestToken, "1234");

calls.createAndWait()

Initiates a call and waits until it reaches a terminal state. Uses SSE first, with automatic polling fallback.

TypeScript
import { PineVoice } from "pine-voice";

const { requestToken } = await PineVoice.auth.requestCode("you@example.com");
const { accessToken, userId } = await PineVoice.auth.verifyCode(
  "you@example.com",
  requestToken,
  "1234",
);

const client = new PineVoice({ accessToken, userId });

const result = await client.calls.createAndWait({
  to: "+14155551234",
  name: "Dr. Smith Office",
  context: "Local dentist office. Open Mon-Fri 9am-5pm.",
  objective: "Schedule a dental cleaning for next Tuesday afternoon",
  caller: "communicator",
});

console.log(result.status);
console.log(result.transcript);

Errors

Error classWhen
PineVoiceErrorBase class for all SDK errors.
AuthErrorAuthentication failures, missing credentials, expired tokens.
CallErrorCall-specific failures such as invalid phone or policy rejection.
RateLimitErrorRate limit exceeded (429).

Error Codes

All errors follow a standard JSON response shape and include a machine-readable code plus HTTP status.

CodeHTTPMeaning
AUTH_REQUIRED401Missing or invalid Authorization or X-Pine-User-Id header.
TOKEN_EXPIRED401Access token expired. Repeat the email verification flow.
SUBSCRIPTION_REQUIRED403No active Pine subscription for this account.
INSUFFICIENT_CREDITS402Not enough credits to place a call.
INVALID_PHONE400Phone number is invalid or unsupported.
INSUFFICIENT_DETAIL400The objective or context is too vague for the agent to act.
RATE_LIMITED429Concurrent limits exceeded.
DND_BLOCKED403Target number is blocked by do-not-call controls.
POLICY_VIOLATION403Call rejected by policy or safety checks.
NOT_FOUND404The specified call_id does not exist.

Rate Limits

Voice calls are English-only today. Supported phone regions include the US, Canada, Puerto Rico, UK, Australia, New Zealand, Singapore, Ireland, and Hong Kong. All numbers must be E.164 formatted.

5 concurrent calls

Per user, with a single-call max duration of 120 minutes.

Credits on terminal response

Completed call responses include credits_charged, so you can attribute usage inside your product.

Developer Preview

The surface will continue to evolve while we harden production workflows, pricing, and developer tooling.