Integrations·Updated Jun 5, 2026
Push API
Programmatically submit calls for analysis via API.
Overview
The Push API lets you programmatically submit calls for analysis. This is useful when:
You have recordings in your own systems
You're building custom integrations
You need to process calls from unsupported platforms
You want to automate bulk uploads
Recommended Authentication
API authentication requires a Push API key generated from Integrations > Push API.
Pass your key in a request header — one of:
X-API-Key header (preferred): X-API-Key: pk_your_key_here
Authorization header: Authorization: Bearer pk_your_key_here
Your team is inferred from the API key, so you do not need to pass a team ID in the body.
Keys are shown once when generated. Store them securely and rotate if exposed.
Submitting a Call
- Basic workflow:
- 1. Generate an API key from Integrations > Push API
- 2. Prepare your call recording and metadata
- 3. Make a POST request to /api/integrations/push-api/ingest
- 4. Include at least one of transcript or audioUrl
- 5. Add optional fields like repName, repEmail, callTitle, duration, callDate, tags, notes, metadata, and title-control flags
- 6. Receive call ID in response
- 7. Wait for analysis to complete in call history
Request Format
Required:
- transcript or audioUrl (at least one is required)
Optional (camelCase or snake_case supported):
- repName / rep_name
- repEmail / rep_email
- callTitle / call_title
- disableAiTitleGeneration / disable_ai_title_generation (boolean, default false)
- useAiCallTitle / use_ai_call_title (boolean alias; inverse of disableAiTitleGeneration)
- callDate / call_date (ISO date)
- audioUrl / audio_url
- duration (minutes, seconds, or ms; normalized automatically)
- tags / callTags / call_tags (array of strings; max 20 tags, 50 characters each)
- notes / callNotes / call_notes (free-text call notes; max 2000 characters)
- metadata (flat key/value object; max 20 keys)
An inline transcript is capped at 500 KB — longer transcripts are truncated. For long calls, send audioUrl instead so Kendo transcribes the full recording.
Tags and notes appear in the call's Tags and Notes sections. They are attached to the rep the call is matched to via repEmail, or to the team owner when no rep matches.
Endpoint and Example
Endpoint: POST https://app.kendo.ai/api/integrations/push-api/ingest
All Push API examples in these docs use the app.kendo.ai host — use that consistently.
Required headers:
- Content-Type: application/json
- X-API-Key: pk_your_key_here (or Authorization: Bearer pk_your_key_here)
Example body:
{ "transcript": "Rep: Thanks for joining.", "callTitle": "Demo Call", "disableAiTitleGeneration": true, "repEmail": "rep@company.com", "duration": 18, "tags": ["inbound", "follow-up"], "notes": "Prospect asked for a follow-up demo next week.", "metadata": { "source": "hubspot", "recordId": "12345" } }
Rate Limits
API rate limits:
- 30 requests per minute per API key
- Request body max size is 10 MB (a larger body returns 413)
- Handle 429 responses with retry/backoff
- Handle 401 for missing/invalid API keys
- Handle 402 — your team's live call hours are exhausted. Add capacity (or enable auto-recharge) and retry.
Each submitted call uses live call capacity in your workspace.
Processing Behavior
If you send audioUrl, Kendo starts audio transcription and analysis.
If you send only transcript, Kendo starts transcript-only analysis.
If both are sent, audio is prioritized for transcription and the inline transcript is not persisted as the primary transcript.
Successful ingestion returns 201 with a callId that you can store for auditing.
Response data includes status context fields like processingTriggered, processingError, and statusReason.
Push API calls that remain pending beyond the processing timeout are automatically marked failed with a clear timeout reason.
How Call Titles Are Determined
By default, Kendo generates the call title with AI from the transcript. In this default mode your callTitle is not used as the displayed title — this is why an imported call can show an AI-written title instead of the one you sent.
To make Kendo use your own title, send both:
- disableAiTitleGeneration: true (or useAiCallTitle: false)
- a non-empty callTitle (or call_title)
When AI title generation is disabled but no callTitle is provided, the call falls back to a generic title, so always pair the flag with a callTitle.
The displayed title is what call history search matches on, so the title you set here is also how the call is found later (see Naming Calls So You Can Find Them).
Naming Calls So You Can Find Them
Call history search matches the call title and the rep name only. It does not search the transcript, the prospect or contact name, tags, or notes.
There is no separate prospect/contact field on a call today, so to find a call by who you spoke with, put that person's name in the callTitle — for example "Discovery - Joe Smith (Acme)".
Because AI title generation overrides your callTitle by default, also send disableAiTitleGeneration: true so your prospect-named title is preserved and stays searchable.
Search is an exact, case-insensitive substring match, not fuzzy — "Joey" will not match a call titled "Joe". Use consistent names so calls stay easy to find.
Tags give a second way to organize: pass tags on ingest (for example the account or prospect name) and filter call history by tag. Tags are filterable but are not matched by the free-text search box.