Meeting and call summaries via API
Getting a transcript is the easy part. Here's how to turn it into a structured meeting summary via API without breaking the budget on long calls.
4 min · · Updated · автоматизация · встречи
Getting a call transcript today isn't the hard part — almost any video conferencing tool or a dedicated speech-to-text service handles that. The hard part starts at the next step: turning 40 minutes of raw text into a structured summary with decisions and action items, without the cost ballooning on longer meetings.
Which call and which model
Send the finished transcript as text to /v1/chat/completions (if your infrastructure is already built around the OpenAI format) or /v1/messages (if the Anthropic style is more convenient). A one-hour meeting transcript usually runs 8-15 thousand words, roughly 12-20 thousand tokens, which fits comfortably within any model's context — Claude and GPT carry a 1,000,000-token window, GLM 128K, so even a three-hour multi-speaker workshop goes through as a single request, no chunking needed.
curl https://api.zukko.pro/v1/chat/completions \
-H "Authorization: Bearer fetch_your_key" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-sol",
"messages": [
{"role": "system", "content": "Summarize the meeting: a Decisions section, a Tasks section with owners, an Open Questions section. Do not restate lines verbatim."},
{"role": "user", "content": "'"$(cat transcript.txt | jq -Rs .)"'"}
]
}'gpt-5.6-sol here is just an example: on Zukko it costs the same as claude-opus-5-5 ($0.30/$0.30 per 1M input/output tokens). If per-volume price matters more for summaries, test gpt-5.6-luna or glm-5.3 (both $0.10/$0.10) on your own recordings.
Structured output instead of a wall of text
A summary with no section breakdown is useless — nobody reads it end to end. A good way to get a machine-readable result is to ask the model to return JSON and render that into a template afterward, say a Notion card or a Telegram message:
import requests, json
resp = requests.post(
"https://api.zukko.pro/v1/chat/completions",
headers={"Authorization": "Bearer fetch_your_key"},
json={
"model": "gpt-5.6-sol",
"messages": [
{"role": "system", "content": (
"Return strict JSON shaped like "
'{"decisions": [...], "tasks": [{"who": "", "what": ""}], "open_questions": [...]}. '
"No text around the JSON."
)},
{"role": "user", "content": open("transcript.txt").read()},
],
},
)
summary = json.loads(resp.json()["choices"][0]["message"]["content"])Idempotency where the transcript arrives via webhook
If the summary job fires from a video conferencing webhook — say, a "recording ready" event — webhooks are often redelivered when the receiver times out. Without protection, the same call gets summarized and billed twice. The fix is an Idempotency-Key keyed on the meeting ID:
curl https://api.zukko.pro/v1/chat/completions \
-H "Authorization: Bearer fetch_your_key" \
-H "Idempotency-Key: meeting-$MEETING_ID" \
-H "Content-Type: application/json" \
-d @payload.jsonA webhook redelivery with the same body within 24 hours returns the already-computed response without a new charge — exactly the scenario this header exists for.
Long multi-hour recordings and cost
For recurring multi-hour workshops, it's worth estimating cost up front with the free token count, if you're using the Anthropic-style mode:
curl https://api.zukko.pro/v1/messages/count_tokens \
-H "Authorization: Bearer fetch_your_key" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model": "claude-sonnet-5", "messages": [{"role": "user", "content": "..."}]}'If you're running hundreds of meetings a month — a call center or a sales team, say — a real saving is enabling caching for repeated operations: if the same transcript gets summarized twice with a fully identical request, for instance a pipeline retry after a client-side timeout, a request with the X-Zukko-Cache: true header (temperature: 0 also enables the cache, but only on models that accept that parameter; Claude models — claude-sonnet-5, claude-opus-5-5 — may reject a temperature other than 1 with a 400, so don't pass it to them) returns the cached response instantly and for free, flagged with X-Zukko-Cache: hit in the response; the cache only works on a fully identical request body, and such hits aren't written to /v1/usage. For chat, cache entries live up to 7 days, enough to cover typical same-day pipeline reruns.
Budget control across teams
If meeting summaries are triggered by several teams — sales, support, engineering — it makes sense to issue each one its own key with its own monthly cap in the dashboard (https://zukko.pro/app/api-keys). That guards against overspend. What it won't do is split spend by team via GET /v1/usage: the history there covers the whole account (all keys together), there's no per-key filter, and the balance is one per account too:
curl https://api.zukko.pro/v1/usage \
-H "Authorization: Bearer fetch_sales_team_key"The endpoint returns the account's cursor-paginated spend history (fields created_at, model, input_tokens, output_tokens, total_tokens, cost_cents, next_cursor). To split spend by team, log X-Zukko-Cost-Micros from every non-streaming response on your side along with the key name — or set up a separate account per team.
Errors specific to this scenario
429 key_daily_limit_reached most likely means someone wired up summarization not just for the final recording but for every intermediate stream chunk. A 402 with the insufficient-balance message means the request never reached a model at all — no summary gets produced, and the pipeline should surface that as an explicit notification to the owner rather than let the job fail silently. If a response cuts off mid-summary, it's almost always max_tokens, not an account-level token limit — for a long meeting with a detailed task list, set max_tokens with headroom, say 4000, rather than leaving the default.
Bottom line: one model picked on price and quality against your own recordings, JSON on output, idempotency keyed on the meeting ID, and separate capped keys per team (plus your own per-key spend log) — with that setup, meeting summaries run at scale without billing surprises or duplicate records.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- An AI agent for job hunting: a résumé tailored to the job and cover lettersWe build a small tool: you give a vacancy text and a file with your real experience, and get a tailored résumé, a letter and a list of gaps. No invented skills.
- Fiction with AI: how to write together, not instead of youHow to work with a model on prose: build a project bible, hold the style, edit in passes and estimate the cost of a long text.
- AI for testers: test cases, checklists and bug reportsHow a QA engineer can use a model for test cases, checklists and bug reports, check coverage, and avoid requirements the model made up.
- Translating subtitles with a neural network: SRT without broken timecodesThe main risk when translating SRT with a neural network is a broken file structure. A scheme where timecodes never reach the model, and a Python script with validation.