Transcribe a link
Send a URL (e.g. a YouTube video) via a source-import — we fetch and transcribe it, and you pick up the resulting transcript_id.
Generate a summary
Request a Smart Report of type summary on a ready transcript and pick up the report or its file export.
Subscribe to an event
Create a webhook for transcript.completed and get notified automatically, without polling.
Transcribe a link or a meeting recording
Instead of uploading a file by hand you can send a public URL or have a bot record a meeting. Both return a job to poll; once ready they carry a transcript_id you read like any transcript.
# Ingest a public URL (a video, a podcast, a file link).
# scope imports:write; rate-limit 30/h.
curl -X POST https://api.vibe2text.ru/api/v1/source-imports/ \
-H 'Authorization: Bearer v2t_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "url": "https://rutube.ru/video/...", "language": "ru" }'
# Poll the import; once it finishes it carries a transcript_id you can read
# exactly like step 6 above.
curl https://api.vibe2text.ru/api/v1/source-imports/{id} \
-H 'Authorization: Bearer v2t_YOUR_TOKEN'
Response
{
"id": "0d5e8f12-3a4b-4c5d-9e0f-112233445566",
"url": "https://rutube.ru/video/...",
"provider": "rutube",
"status": "queued",
"transcript_id": null,
"created_at": "2026-06-04T00:41:00Z"
}
# Send a bot to record a live meeting (scope recordings:write).
# Check GET /recording-jobs/platforms for supported platforms.
curl -X POST https://api.vibe2text.ru/api/v1/recording-jobs/ \
-H 'Authorization: Bearer v2t_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "platform": "yandex_telemost", "meet_url": "https://telemost.yandex.ru/j/..." }'
# Poll the job; when done it links to a transcript_id.
curl https://api.vibe2text.ru/api/v1/recording-jobs/{id} \
-H 'Authorization: Bearer v2t_YOUR_TOKEN'
Response
{
"id": "a1b2c3d4-5e6f-4071-8293-aabbccddeeff",
"platform": "yandex_telemost",
"meet_url": "https://telemost.yandex.ru/j/...",
"status": "scheduled",
"transcript_id": null,
"created_at": "2026-06-04T00:41:00Z"
}
Generate a report
Request a report on a ready transcript (summary, action items, topics), poll its status, and optionally queue a file export.
# Ask for a report on a ready transcript (scopes reports:write + reports:read).
# "type" is required. Pass transcript_id (one) OR transcript_ids (several).
# An Idempotency-Key dedupes retries; you may have 3 LLM jobs in flight (else 429).
curl -X POST https://api.vibe2text.ru/api/v1/smart-reports/ \
-H 'Authorization: Bearer v2t_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: report-9f3e4d3a' \
-d '{ "transcript_id": "9f3e4d3a-1b2c-4d5e-8f90-aabbccddeeff", "type": "summary" }'
Response
{
"id": "59d0af3f-926a-435b-adc4-b1b766bb87bc",
"transcript_id": "9f3e4d3a-1b2c-4d5e-8f90-aabbccddeeff",
"transcript_ids": ["9f3e4d3a-1b2c-4d5e-8f90-aabbccddeeff"],
"type": "summary",
"status": "pending",
"render_mode": "constructor",
"intent": {
"requested_type": "summary",
"render_mode": "auto",
"style_hint": "summary",
"instructions": null,
"model": null,
"transcript_ids": ["9f3e4d3a-1b2c-4d5e-8f90-aabbccddeeff"]
},
"plan": null,
"template_id": null,
"content_md": null,
"created_at": "2026-06-04T00:41:00Z"
}
# Poll the report and read its rendered content.
curl https://api.vibe2text.ru/api/v1/smart-reports/{id} \
-H 'Authorization: Bearer v2t_YOUR_TOKEN'
Response
{
"id": "c7d7a0d3-...",
"transcript_id": "9f3e4d3a-...",
"transcript_ids": ["9f3e4d3a-..."],
"type": "summary",
"status": "completed",
"render_mode": "text",
"content_md": "## Счёт от одного до десяти\n\nВ записи звучит последовательный счёт от 1 до 10.",
"content_blocks": null,
"tokens_input": 420,
"tokens_output": 38,
"error": null,
"created_at": "2026-06-04T00:17Z",
"completed_at": "2026-06-04T00:17Z"
}
# Need a file? Queue an export (scopes exports:write + exports:read):
curl -X POST https://api.vibe2text.ru/api/v1/exports/ \
-H 'Authorization: Bearer v2t_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "transcript_id": "9f3e4d3a-1b2c-4d5e-8f90-aabbccddeeff", "format": "pdf" }'
# Then GET /exports/{id} (poll) and GET /exports/{id}/download for the url.
Response
# POST /exports/ →
{
"id": "b0d7ef8b-1f21-4448-8b50-29e3d06df0b8",
"transcript_id": "9f3e4d3a-1b2c-4d5e-8f90-aabbccddeeff",
"format": "pdf",
"status": "pending",
"size_bytes": null,
"error": null,
"expires_at": "2026-06-11T00:41:18Z",
"created_at": "2026-06-04T00:41:18Z"
}
# GET /exports/{id}/download →
{ "url": "https://media.vibe2text.ru/<pre-signed-download-url>", "expires_in": 3600 }
The shape of the final report is described in a separate JSON Schema file — handy if you want to validate the response on your end: /schemas/report-document.schema.json
Subscribe to webhooks
Give us a URL and the events you care about — we'll POST a notification there the moment something is ready.
# Subscribe to events (scopes webhooks:write + webhooks:read).
# The response includes a secret shown ONCE — store it to verify signatures.
curl -X POST https://api.vibe2text.ru/api/v1/webhooks/ \
-H 'Authorization: Bearer v2t_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://hooks.your-app.com/vibe2text",
"events": ["transcript.completed", "smart_report.generated"]
}'
# Lost the secret? POST /webhooks/{id}/regenerate-secret.
# Test the endpoint with POST /webhooks/{id}/retest. Inspect deliveries
# with GET /webhooks/{id}/logs. (There is no DELETE — disable via PATCH.)
Response
{
"id": "0550f52d-...",
"url": "https://example.com/hook",
"events": ["transcript.completed"],
"secret_hint": "p4-X...zkvI",
"is_active": true,
"last_delivery_at": null,
"last_status_code": null,
"created_at": "2026-06-04T00:41:21Z",
"secret": "whsec_xxxxxxxxxxxxxxxxxxxx"
}
# "secret" is returned ONLY on create (and regenerate-secret) — store it.
# Later reads show only "secret_hint".
Verifying the signature
Every webhook carries a signature in the X-Signature header (format sha256=<hex>). Verify it against the webhook secret over the raw body bytes (before json.loads) — that's how you confirm the message really came from us.
# Verify the signature on every incoming webhook.
# We send the signature in the "X-Signature" request header, formatted as
# "sha256=<hex>". Pass the RAW body bytes (before json.loads) to HMAC.
import hashlib
import hmac
def verify(raw_body: bytes, x_signature_header: str, secret: str) -> bool:
if not x_signature_header or not x_signature_header.startswith("sha256="):
return False
expected = hmac.new(
key=secret.encode("utf-8"),
msg=raw_body, # raw bytes, BEFORE json.loads(...)
digestmod=hashlib.sha256,
).hexdigest()
provided = x_signature_header.removeprefix("sha256=")
return hmac.compare_digest(expected, provided)
Event list
transcript.createdtranscript.completedtranscript.failedsmart_report.generatedexport.completedaction_item.createdpayment.succeededpayment.failed