Developers

Create a key, then call these tools from your own application — chat, lesson plans and PowerPoint decks, and call transcription.

Your API keys

A key is shown once, when you create it. We store only a hash, so it cannot be recovered later.

Loading…

Getting started

If you have never called an API before, start here. Three steps and you are done.

Step 1 — Create a key

Use the box above. Give it a name so you remember what it is for, and press Create key. You will see something like:

yg_live_xK9mQ2vB7nR4tL8wY6pZ3jH5sD1fG0aC

Copy it immediately. We store only a scrambled version, so we cannot show it to you again. If you lose it, revoke it and create another — that is normal and costs nothing.

Step 2 — Keep it secret

Anyone with this key can use your account. Treat it like a password:

If it leaks, press Revoke here. It stops working instantly.

Step 3 — Make your first call

Open a terminal and paste this, replacing the key with yours:

curl -X POST https://ai.yugam.co/api/v1/chat \
  -H "X-API-Key: yg_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Say hello in Hindi"}'

You should get back:

{"reply": "नमस्ते! आप कैसे हैं?", "mode": "balanced"}

That is it. Everything below is detail on top of that.

What the pieces mean

PieceWhat it is
curlA program for calling APIs. Built into Mac and Linux; on Windows use PowerShell or Git Bash.
-X POST"I am sending you something", as opposed to just asking for a page.
-HA header — extra information attached to the request. Your key goes in one.
-dThe data you are sending, written as JSON.
X-API-KeyThe header we look at to know who you are. Every request needs it.

Chat

Send text, get text back.

POST/api/v1/chat

The simplest form — one question, one answer:

curl -X POST https://ai.yugam.co/api/v1/chat \
  -H "X-API-Key: yg_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Write a note to parents about sports day."}'

Choosing speed vs quality

Add mode. If you leave it out you get balanced.

ModeSpeedUse it for
fast~26 words/secShort answers, simple rewrites
balanced~11 words/secMost things. The default.
thinkingSlowestProblems needing step-by-step reasoning
-d '{"prompt": "Explain photosynthesis to a 10 year old", "mode": "fast"}'

Having a conversation

The server remembers nothing between requests. To continue a conversation, send the whole history each time using messages instead of prompt:

{
  "messages": [
    {"role": "user",      "content": "What is the capital of India?"},
    {"role": "assistant", "content": "New Delhi."},
    {"role": "user",      "content": "What is its population?"}
  ]
}

role is user for the person and assistant for previous replies.

In Python

import requests

r = requests.post(
    "https://ai.yugam.co/api/v1/chat",
    headers={"X-API-Key": "yg_live_your_key_here"},
    json={"prompt": "Summarise this in one line: ..."},
    timeout=900,
)
print(r.json()["reply"])

In Node.js

const r = await fetch("https://ai.yugam.co/api/v1/chat", {
  method: "POST",
  headers: {
    "X-API-Key": "yg_live_your_key_here",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ prompt: "Say hello" }),
});
const data = await r.json();
console.log(data.reply);

Answers take time. This runs on our own server, not a giant cloud cluster. A long answer can take several minutes. Set your timeout to at least 900 seconds, or your code will give up before we finish.

Lesson plans & PowerPoint

Send a topic and a class. Get back a timed lesson plan, and a PowerPoint deck you can project.

POST/api/v1/lessons/pptx

The short way — one call, and a .pptx file lands on your disk:

curl -X POST https://ai.yugam.co/api/v1/lessons/pptx \
  -H "X-API-Key: yg_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"topic": "Photosynthesis", "grade": "Grade VII", "subject": "Science", "minutes": 40}' \
  -o lesson.pptx

The plan is saved too, so you can fetch it again as JSON or re-download the deck later.

What you can send

FieldRequiredAllowedMeaning
topicyes2–200 charactersWhat the lesson is about
gradeyes1–40 charactersThe class, e.g. Grade VII
subjectnoup to 80 charactersHelps pitch the language and examples
minutesno10–180, default 40Length of the period
segmentsno3–8, default 5How many parts the lesson is split into

POST/api/v1/lessons

The same thing, but returns the plan as JSON instead of a file:

{
  "id": "df049d3bdd01",
  "created_at": "2026-09-04T11:30:45+00:00",
  "pptx_url": "/api/v1/lessons/df049d3bdd01/pptx",
  "plan": {
    "title": "Photosynthesis Lesson Plan",
    "summary": "...",
    "objectives": ["...", "...", "..."],
    "materials":  ["...", "...", "..."],
    "segments": [
      {"title": "Introduction", "minutes": 5,
       "points": ["Hello class, today we will learn about photosynthesis.", "..."],
       "activity": "Show a diagram of photosynthesis and ask what they notice."}
    ],
    "homework": "Draw a diagram of photosynthesis and write a short paragraph."
  }
}

The segment minutes always add up to exactly the minutes you asked for — we correct the total before saving, so you never get a 40-minute period whose parts sum to 37.

GET/api/v1/lessons/{id}/pptx — download the deck

curl https://ai.yugam.co/api/v1/lessons/df049d3bdd01/pptx \
  -H "X-API-Key: yg_live_your_key_here" \
  -o lesson.pptx

The deck is a title slide, a plan-at-a-glance slide showing the timing, one slide per segment, and a homework slide. 16:9, in the school's colours.

In Python

import requests

KEY = {"X-API-Key": "yg_live_your_key_here"}

# One call, straight to a file
r = requests.post(
    "https://ai.yugam.co/api/v1/lessons/pptx",
    headers=KEY,
    json={"topic": "Fractions", "grade": "Grade V", "subject": "Maths", "minutes": 35},
    timeout=1200,
)
r.raise_for_status()
open("fractions.pptx", "wb").write(r.content)

# Or get the plan first, and read it before deciding
plan = requests.post(
    "https://ai.yugam.co/api/v1/lessons",
    headers=KEY,
    json={"topic": "Fractions", "grade": "Grade V", "segments": 6},
    timeout=1200,
).json()

for seg in plan["plan"]["segments"]:
    print(f"{seg['minutes']:>3} min  {seg['title']}")

In Node.js

import { writeFile } from "node:fs/promises";

const r = await fetch("https://ai.yugam.co/api/v1/lessons/pptx", {
  method: "POST",
  headers: {
    "X-API-Key": "yg_live_your_key_here",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ topic: "The Water Cycle", grade: "Grade VI", minutes: 40 }),
});
if (!r.ok) throw new Error((await r.json()).error.message);
await writeFile("water-cycle.pptx", Buffer.from(await r.arrayBuffer()));

A plan takes several minutes — about 4 to 6 on the current server, and longer if someone else is generating one at the same time, because the server writes one at a time. Set your timeout to at least 1200 seconds. Unlike call recordings, there is no queue to poll: the request stays open until the plan is done.

Managing saved plans

RouteWhat it does
GET /api/v1/lessonsRecent plans, newest first. ?limit= up to 100.
GET /api/v1/lessons/{id}One plan in full
DELETE /api/v1/lessons/{id}Delete a plan

Plans are shared across the team — a listing shows everyone's, with owner_email saying who generated each one.

Call recordings

Upload audio, get a transcript and a full analysis of the call.

How it works

Processing happens in two stages, and you can see both:

StageWhat happensStatus you will see
1. TranscribeSpeech becomes texttranscribing
2. AnalyseText becomes a structured recordsummarising
FinishedEverything is readydone

Uploading returns immediately with an id. You then poll — ask for the result every 30 seconds or so until status is done.

POST/api/v1/calls — upload

curl -X POST https://ai.yugam.co/api/v1/calls \
  -H "X-API-Key: yg_live_your_key_here" \
  -F "file=@recording.mp3"

-F attaches a file. The @ means "read from this path". The field must be called file.

{"id": "9174c1d4ac87", "status": "queued", "filename": "recording.mp3"}

Accepted: mp3, wav, m4a, mp4, ogg, opus, aac, amr, flac, webm. Up to 500 MB. A 5-minute call takes a few minutes to process.

Processing is slow on the current server. Recordings are processed one at a time; a 10-minute call can take an hour or more, and the rest wait their turn as queued. Poll the call until its status is done.

GET/api/v1/calls/{id} — get the result

curl https://ai.yugam.co/api/v1/calls/9174c1d4ac87 \
  -H "X-API-Key: yg_live_your_key_here"

Polling in Python

import requests, time

H = {"X-API-Key": "yg_live_your_key_here"}

up = requests.post("https://ai.yugam.co/api/v1/calls",
                   headers=H, files={"file": open("call.mp3", "rb")})
call_id = up.json()["id"]

while True:
    r = requests.get(f"https://ai.yugam.co/api/v1/calls/{call_id}", headers=H).json()
    if r["status"] in ("done", "failed"):
        break
    print("still", r["status"], "…")
    time.sleep(30)

print(r["transcript"])
print(r["record"]["summary"])
print("Coaching:", r["record"]["coaching_note"])

What you get back

Three groups: the words, measured delivery, and the analysis.

1. The transcript

{
  "transcript": "नमस्कार सर, मैं ... से बात कर रही हूँ ...",
  "words": 427,
  "duration_s": 274.6,
  "needs_review": true,
  "review_reason": "one word repeats 6 times in a row — part of the audio was not understood"
}

Always check needs_review. When it is true, the recogniser struggled and the transcript may be unreliable. Show the warning to your users rather than presenting the result as fact.

2. Measured delivery — metrics

Counted from the audio, not judged by a model. Useful for coaching.

FieldMeaningWhat to look for
loudness_dbAverage levelBelow −30 is very quiet; accuracy suffers
peak_dbLoudest momentNear 0 means clipping
talking_pct% of the call with speechVery high can mean nobody paused to listen
words_per_minSpeaking paceOver ~180 is rushed; under ~100 is hesitant
pausesNumber of silences over 0.6sVery few suggests a scripted monologue
longest_pause_sLongest silenceA long gap may be a dropped line

3. The analysis — record

{
  "record": {
    "parent_name": "Ravi",
    "child_current_school": "केंद्रीय विद्यालय",
    "grade_enquired_for": "not stated",
    "locality": "Kalyanpur",
    "enquiry_source": "Facebook",
    "is_existing_parent": "no",
    "fee_discussed": "yes",
    "campus_visit_offered": "yes",
    "visit_outcome": "vague / no commitment",
    "objections": ["no time", "happy with current school"],
    "next_step": "call back at 2pm",
    "interest_level": "warm",

    "call_purpose": "first contact",
    "outcome": "information given",
    "what_happened": "The counsellor opened by introducing the school ...",
    "topics_covered": ["hostel", "sports", "fees"],
    "questions_parent_asked": ["What is the annual fee?"],

    "counsellor_tone": "warm",
    "listened_well": "partly",
    "asked_discovery_questions": "yes",
    "handled_objections": "partly",
    "asked_for_commitment": "no",
    "call_quality_score": 3,
    "what_went_well": ["Explained the sports programme clearly"],
    "what_to_improve": ["Never asked for a specific visit date"],
    "coaching_note": "You built rapport well, but the call ended without ..."
  }
}

Field reference

FieldPossible values
interest_levelhot · warm · cold · not stated
call_purposefirst contact · follow up · callback scheduling · qualification · visit booking · other
outcomevisit booked · callback agreed · information given · no progress · wrong person
visit_outcomedate agreed · declined · vague / no commitment · not stated
counsellor_tonewarm · neutral · rushed · pushy · unclear
listened_wellyes · partly · no
handled_objectionsyes · partly · no · none raised
call_quality_score1 to 5 (5 = clear next step agreed and parent felt heard)

Any text field can be the literal string "not stated". That means the call did not cover it — it is not an error, and not a guess. Handle it in your code.

POST/api/v1/calls/{id}/reanalyse

Redo only the analysis, keeping the existing transcript. Much faster and cheaper than re-uploading, because transcription is the slow part.

curl -X POST https://ai.yugam.co/api/v1/calls/9174c1d4ac87/reanalyse \
  -H "X-API-Key: yg_live_your_key_here"

GET/api/v1/calls — list recent

curl https://ai.yugam.co/api/v1/calls -H "X-API-Key: yg_live_your_key_here"

When something goes wrong

Every error looks the same and tells you what to do next. There is only ever one shape to handle.

{
  "error": {
    "code":    "invalid_api_key",
    "message": "That API key is not valid, or it has been revoked.",
    "hint":    "Check the key, or create a new one on the Developers page."
  }
}

Check error.code in your program; show error.message to a person. hint is not always present.

The ones you are most likely to see

CodeHTTPWhat to do
not_authenticated401You sent no key. Add the X-API-Key header.
invalid_api_key401Wrong key, or it was revoked. Create a new one above.
bad_request400Something in your JSON is missing or out of range. The message names the field.
not_found404No plan or call with that id.
timeout504Your request took too long. Raise your client timeout to 1200s.
processing_paused503New call recordings are not being accepted on this server. Existing calls can still be read.
model_unavailable503The server is restarting. Wait a minute and retry.
generation_failed502The plan came back unusable. Retry, or rephrase the topic more plainly.
too_many_keys409You have 10 active keys. Revoke one first.
file_too_large413The recording is over 500 MB. Compress or split it.
unsupported_file415Not an audio format we read. See the accepted list above.

Retry on 502, 503 and 504 — not on 400 or 401. The first three mean the server had a bad moment and the same request may well work next time. The last two mean the request itself is wrong, and sending it again will fail identically.

One generation at a time. The server runs a single model job at once, so if a colleague is generating a lesson plan your request waits behind theirs. That waiting is on top of the request's own time, which on the current server is minutes, not seconds; hence the long timeouts.