Skip to content
DikoAPI
API keys

Quickstart

Open as Markdown

From creating a key to reading your first transcript in a few minutes.

In this guide you create a key, make a first call that reads your own data, import a public YouTube video and read its transcript. Every example uses the base URL https://api.diko.app/api/v1.

1. Create an API key

  1. Sign in to Diko and open Nustatymai → API (Settings → API), the API keys page (/settings/api). The old /kurejams link redirects there. You need the Verslas plan.
  2. Choose Sukurti raktą (Create key), enter a name and pick the Skaitymas ir importas (Read and import) scope template (meetings:read, library:write). The default expiry is 90 days.
  3. Confirm the action by signing in again if Diko asks for it.
  4. Copy the key. It is shown only once; afterwards you only see a hint such as dk_live_Ab12…9xYz.

Keep the key in an environment variable, not in code:

Shell
export DIKO_API_KEY="dk_live_..."

2. Make your first call

Start with a call that returns your own data. The Skaitymas ir importas (Read and import) template covers both lists below: library:write includes library:read, and meetings:read is listed separately. Set the base URL and headers once; the later steps reuse them.

Library transcripts

GET /library/transcripts?limit=1 returns the most recently added transcript in your library. It needs library:read (or library:write, which includes it).

cURL
curl "https://api.diko.app/api/v1/library/transcripts?limit=1" \
  -H "Authorization: Bearer $DIKO_API_KEY"

The response is a list. data holds the items (an empty array if the library has no transcripts yet), has_more tells you whether another page exists and next_cursor is how you fetch it (Pagination):

JSON
{
  "object": "list",
  "data": [
    {
      "id": "trn_ZFF3NHc5V2dYY1E",
      "object": "library_transcript",
      "title": "Kaip veikia transkribavimas",
      "source_type": "youtube",
      "youtube_video_id": "dQw4w9WgXcQ",
      "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
      "channel": "Diko",
      "language": "lt",
      "duration_ms": 212000,
      "transcription_method": "captions",
      "summary": { "status": "ready", "text": null },
      "categories": ["Technologijos"],
      "added_at": "2026-10-11T09:30:00.000Z",
      "archived": false,
      "segment_count": 120,
      "revision": "r_6f6f4bb9762915b561878fd1e1fa7f56",
      "web_url": "https://studio.diko.app/library/dQw4w9WgXcQ"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Meetings

If the key has meetings:read, GET /meetings?limit=1 returns your latest meeting in the same list format:

cURL
curl "https://api.diko.app/api/v1/meetings?limit=1" \
  -H "Authorization: Bearer $DIKO_API_KEY"

A meeting item has an id (mtg_...), title, status, processing, transcript and minutes. Participants, speakers and counts come only from GET /meetings/{meeting_id}.

If the first call fails

  • 401 means the key itself was not accepted: missing_api_key, invalid_api_key, api_key_expired, api_key_revoked or api_key_disabled. Check that DIKO_API_KEY is set and that the key is still active.
  • 403 insufficient_scope means the key is valid but lacks the scope this endpoint needs. For example, a key with only library:read calling GET /meetings:
HTTP
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer realm="diko", error="insufficient_scope", scope="meetings:read"
JSON
{
  "type": "error",
  "error": {
    "type": "permission_error",
    "code": "insufficient_scope",
    "message": "The API key lacks the permission this endpoint needs.",
    "doc_url": "https://diko.app/en/api-docs/errors#insufficient_scope",
    "details": {
      "required_scopes": ["meetings:read"],
      "granted_scopes": ["library:read"]
    }
  },
  "request_id": "req_QBPIQ5QTIWAUYTMDNCLD7CMKBE"
}

details.required_scopes is what the endpoint needs and details.granted_scopes is what your key has. Scopes cannot be changed after a key is created, so create a new key with the right scope (Scopes). Other 403 codes (plan_required, ip_not_allowed and so on) are in the error catalog.

3. Import a YouTube video

POST /library/imports needs library:write (the Skaitymas ir importas template has it). It starts an asynchronous import and never waits for a download. Always send an Idempotency-Key: if the request is interrupted, you can repeat the same request with the same key and the import is not created twice.

cURL
curl -X POST "https://api.diko.app/api/v1/library/imports" \
  -H "Authorization: Bearer $DIKO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'

The response is 201 Created with a Location header. A video imported for the first time starts at queued:

JSON
{
  "id": "imp_6Mfj7Oxm4MfxGGmZRhiUQf",
  "object": "library_import",
  "status": "queued",
  "stage": null,
  "queue_position": 1,
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "youtube_video_id": "dQw4w9WgXcQ",
  "language": null,
  "reused": false,
  "transcript_id": null,
  "error": null,
  "created_at": "2026-10-11T09:30:00.000Z",
  "updated_at": "2026-10-11T09:30:00.100Z",
  "completed_at": null
}

If the transcript is already in your library or in the shared cache, the import becomes succeeded at once with reused: true and no credits are used.

4. Wait for the result

You can poll the import status or get a webhook.

Polling

While the import has not reached a final status, GET /library/imports/{import_id} returns the header Retry-After: 3. Poll no more often than that and set an overall deadline:

cURL
curl "https://api.diko.app/api/v1/library/imports/imp_6Mfj7Oxm4MfxGGmZRhiUQf" \
  -H "Authorization: Bearer $DIKO_API_KEY"

A long video can take longer than your deadline. Then leave the loop and check again later, or use webhooks.

Import statuses and errors

An import has one of these status values. succeeded, failed and canceled are final.

status Meaning
queued waits in the queue; queue_position shows your place
processing running; stage names the step
canceling you asked to cancel a running import; it ends as canceled when the work stops
succeeded done; transcript_id is set
failed stopped by an error; error.code says why
canceled canceled by you or by the system. The system cancels an import when its key is revoked, disabled, deleted or rotated without an overlap period, when the key is revoked after a leak, and when API access is suspended. A queued import ends canceled at once, a running one goes through canceling. Work already done is charged as usual. A rotation with a grace period does not cancel it

While the import is processing, stage is one of: captions (Diko looks for YouTube captions), waiting (waits for a free speech-recognition slot), downloading, transcribing or summarizing. In every other status stage is null.

A failed import carries error.code:

error.code Meaning
video_unavailable, video_private, age_restricted the video cannot be fetched; a retry does not help
video_too_long the video is longer than the limit for speech recognition (currently 4 hours)
video_duration_unknown Diko could not read the duration of the video
captions_unavailable captions could not be retrieved
download_failed, transcription_failed the download or the transcription failed; try again later
transcription_timeout the import stayed queued for more than 24 hours or processing for more than 6 hours
provider_limit a caption provider limit was reached; try again later
insufficient_credits there were not enough credits to finish the import
internal_error an error on Diko’s side; try again later

To try again, create a new import with a new Idempotency-Key.

Credits. A transcript that is already in your library or in the shared cache costs nothing (reused: true). Otherwise Diko checks your credit balance when it creates the import and again before paid work. GET /me shows the balance for a key with library:write. Credit rates and plan allowances are on the pricing page (in Lithuanian).

Webhook

Create an endpoint under Nustatymai → API → Webhooks (/settings/api/webhooks) and choose the events library.import.succeeded, library.import.failed and library.import.canceled. Diko sends a POST request to your address when the import ends. Signature verification and retries are described on Events and webhooks.

5. Read the transcript

When the import is succeeded, transcript_id is the trn_... ID of a transcript that is now in your library (it also appears in the GET /library/transcripts list from step 2). Fetch its text:

cURL
# The whole text with timestamps (use the transcript_id from the import)
curl "https://api.diko.app/api/v1/library/transcripts/trn_ZFF3NHc5V2dYY1E/transcript?format=text" \
  -H "Authorization: Bearer $DIKO_API_KEY"

The text comes as lines [HH:MM:SS] Name: text. Want segments as JSON, SRT or VTT? See getLibraryTranscriptTranscript.

Check what your key can do (GET /me)

GET /me is account metadata, not your data. It works with any valid key, so it is a quick way to see which key you are using, whether the account may use the API and, for a key with the library:write scope, what the credit balance is. Use it when something does not work as expected, not as the first call.

cURL
curl "https://api.diko.app/api/v1/me" \
  -H "Authorization: Bearer $DIKO_API_KEY"

The access part of a successful response looks like this:

JSON
{ "allowed": true, "reason": "subscription", "plan": "verslas" }

When allowed is false, reason says why (for example plan_required). The meaning of every code is in the error catalog.

GET /me follows least privilege, so a narrowly scoped key never reveals more than it needs. user.email is always masked, and credits is filled in only for a key with library:write, the only scope that spends credits:

JSON
{
  "user": { "id": "usr_4iAD1dYhdAEJIkMN5GPczR", "object": "user", "email": "j***@example.com", "display_name": "Jonas" },
  "credits": { "scope": "user", "available": "123.5000", "as_of": "2026-10-11T09:30:00.000Z" }
}

For a read-only key (meetings:read, library:read) the same response has "credits": null. GET /me has its own, stricter rate limit (Rate limits), so do not call it in a loop.

What next

  • Errors: how to handle every code and when to retry.
  • Rate limits: request and import limits.
  • Meetings: read meeting transcripts, minutes and action items with meetings:read.

Search for a topic, an endpoint or an error code.

Search across all documentation pagesesc close