Skip to main content

POST /api/v1/calls/ingest

Ingest a call recording or transcript for AI-powered intent classification and optional Google Ads conversion tracking.

Request

POST https://app.trolleyshield.com/api/v1/calls/ingest
Authorization: Bearer tsk_your_api_key_here
Content-Type: application/json

Body

{
"tracking_number": "+15551234567",
"caller": "+15559876543",
"caller_name": "Jimmy Pesto, Sr.",
"transcript": "Hi, I'm calling about getting a quote for a new roof...",
"duration": 145,
"call_time": "2026-03-25T14:30:00Z",
"external_call_id": "call_abc123",
"gclid": "CjwKCAiAhreqBhAvEiwAQWDgMrxZ...",
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "roofing_dallas",
"business_context": "Residential roofing company in Dallas, TX"
}

Required Fields

FieldTypeDescription
tracking_numberstringThe tracking phone number (normalized automatically)
transcriptstring*Call transcript text
audio_urlstring*URL to audio file for automatic transcription

* Either transcript or audio_url is required. If both are provided, transcript takes priority.

Optional Fields

FieldTypeDescription
callerstringCaller phone number
caller_namestringCaller ID name (displayed in call views)
durationintegerCall duration in seconds (defaults to 0)
call_timestringISO 8601 datetime of the call
external_call_idstringYour system's call ID (used for deduplication)
caller_citystringCaller's city
caller_statestringCaller's state
caller_countrystringCaller's country
is_voicemailbooleanMark as voicemail (defaults to false)
business_contextstringOverride account-level business context for this analysis

Attribution Fields

FieldTypeDescription
gclidstringGoogle Click ID for conversion tracking
gbraidstringGoogle brand ID (iOS)
wbraidstringWeb-to-App bridge ID
fbclidstringFacebook Click ID
msclidstringMicrosoft Click ID
utm_sourcestringMarketing source (e.g. google, facebook)
utm_mediumstringMarketing medium (e.g. cpc, organic, email)
utm_campaignstringCampaign name
utm_termstringSearch keywords
utm_contentstringAd content variant
landing_pagestringLanding page URL
referrerstringReferrer URL
ga_client_idstringGoogle Analytics client ID (_ga cookie value) for GA4 session stitching
fbpstringFacebook browser ID (_fbp cookie value) for Meta CAPI matching
tip

You don't need to provide business_context in every request — it's automatically pulled from your account settings. Set it in Settings → General → Business Context.

Response

Success (201)

{
"call_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"transcript_status": "completed",
"intent": "qualified_lead",
"confidence": 92,
"reasoning": "Caller is requesting a specific service quote with timeline and budget discussion.",
"action": "convert",
"conversion_queued": true
}
FieldTypeDescription
call_idstringUUID of the created call record
transcript_statusstringcompleted, pending, or failed
intentstring | nullAI classification (see table below)
confidencenumber | nullConfidence score (0-100)
reasoningstring | nullExplanation of the classification
actionstring | nullRecommended action
conversion_queuedbooleanWhether a Google Ads conversion was queued

Intent Values

IntentActionDescription
qualified_leadconvertActively looking to purchase, book, or commit
general_inquiryignoreEarly research, price shopping, gathering info
existing_customerignoreReferences past orders, account, or previous interactions
spamblockTelemarketer, robocall, or solicitation
wrong_numberignoreReached wrong business or unrelated services
job_seekerignoreEmployment inquiry or resume submission
vendorignoreB2B sales call from supplier or service provider
incompleteignoreDropped call, too short, or no conversation

Error Responses

StatusErrorDescription
400Invalid requestMissing required fields or validation failure
401Missing or invalid API keyNo Bearer token or key doesn't exist
403API access requires a paid planAccount is on free tier
403Call plan requiredAccount is on a Form Shield-only plan
404Tracking number not foundNo matching tracking number in your account
409Duplicate callexternal_call_id already exists
429Usage limit exceededTrial/free tier limit reached
500Internal server errorSomething went wrong on our end

Example: Node.js

const response = await fetch('https://app.trolleyshield.com/api/v1/calls/ingest', {
method: 'POST',
headers: {
'Authorization': 'Bearer tsk_your_api_key_here',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tracking_number: '+15551234567',
caller: '+15559876543',
caller_name: 'Jimmy Pesto, Sr.',
transcript: 'Hi, I need a quote for roof repair on my home...',
duration: 180,
gclid: 'CjwKCAiAhreqBhAvEiwAQWDgMrxZ...',
utm_source: 'google',
utm_medium: 'cpc',
utm_campaign: 'roofing_dallas',
}),
});

const result = await response.json();
console.log(`Intent: ${result.intent}, Action: ${result.action}`);

if (result.conversion_queued) {
console.log('Google Ads conversion queued for upload');
}

Example: Python

import requests

response = requests.post(
'https://app.trolleyshield.com/api/v1/calls/ingest',
headers={
'Authorization': 'Bearer tsk_your_api_key_here',
'Content-Type': 'application/json',
},
json={
'tracking_number': '+15551234567',
'caller': '+15559876543',
'caller_name': 'Jimmy Pesto, Sr.',
'transcript': 'Hi, I need a quote for roof repair on my home...',
'duration': 180,
'gclid': 'CjwKCAiAhreqBhAvEiwAQWDgMrxZ...',
'utm_source': 'google',
'utm_medium': 'cpc',
'utm_campaign': 'roofing_dallas',
},
)

result = response.json()
print(f"Intent: {result['intent']}, Action: {result['action']}")

Example: cURL

curl -X POST https://app.trolleyshield.com/api/v1/calls/ingest \
-H "Authorization: Bearer tsk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"tracking_number": "+15551234567",
"caller": "+15559876543",
"caller_name": "Jimmy Pesto, Sr.",
"transcript": "Hi, I need a quote for roof repair on my home...",
"duration": 180,
"gclid": "CjwKCAiAhreqBhAvEiwAQWDgMrxZ...",
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "roofing_dallas"
}'

Deduplication

If you provide external_call_id, the API will reject duplicate submissions with a 409 status. This lets you safely retry failed requests without creating duplicate records.

Conversion Tracking

When a call is classified as qualified_lead and meets the confidence and duration thresholds, and a gclid, gbraid, or wbraid is provided, a conversion record is automatically queued for upload to Google Ads.

You can configure conversion thresholds per tracking number:

  • Conversion Action — which Google Ads conversion to fire
  • Conversion Value — dollar amount to report
  • Min Confidence — minimum AI confidence score (default: 80)
  • Min Duration — minimum call length in seconds (default: 60)
  • Qualifying Intents — which intents trigger conversions (default: qualified_lead)

To use conversion tracking, connect your Google Ads account in Settings → Integrations → Google Ads.

Attribution

Attribution fields (utm_source, utm_medium, utm_campaign, gclid, etc.) are stored with the call record and displayed in the call detail view under Source Attribution. This gives you visibility into which marketing channels drive each call.

When gclid is provided alongside a qualifying call, Google Ads can attribute the offline conversion back to the specific ad click.