All guides
REST API · v1

API documentation

Identify movies by frame or text description — directly from your app, extension or bot. One HTTP request, JSON response with full movie metadata and confidence score.

JSON over HTTPS Bearer auth 120 req/hour en · ru

Quickstart

  1. 1

    Get a key

    Open the developer dashboard and submit a request. A key is issued immediately — but in "pending" status.

  2. 2

    Wait for activation

    We'll contact you for activation and payment. Then status becomes "active".

  3. 3

    Make your first call

    Pass the key as Authorization: Bearer header and POST to /v1/identify.

curl -X POST https://bdkino.com/api/v1/identify \
  -H "Authorization: Bearer bdk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "robot collects garbage on an abandoned Earth",
    "lang": "en"
  }'

Authentication

Every request must contain an Authorization header with an active key. Without it — 401.

HTTP Header
Authorization: Bearer bdk_live_xxxxxxxxxxxx
Do
  • Keep the key on the server only
  • Always use HTTPS
  • Rotate keys every 6 months
Don't
  • Never expose the key in frontend / git / Discord
  • No plain HTTP — HTTPS only
  • Don't share keys between projects — get a separate one

Endpoint: identify a movie

POSThttps://bdkino.com/api/v1/identify

Accepts an image (base64) and/or text description. Returns matches from the bdkino database sorted by confidence.

Request parameters

FieldTypeRequiredDescription
image_base64stringone of*JPEG/PNG/WebP in base64, up to 15 MB.
descriptionstringone of*Scene description, 3–2000 chars.
langstringResponse metadata language: "en" or "ru". Default "en".

* At least one — image_base64 OR description must be provided (both allowed).

Example: search by description

curl -X POST https://bdkino.com/api/v1/identify \
  -H "Authorization: Bearer bdk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "robot collects garbage on an abandoned Earth",
    "lang": "en"
  }'

Example: search by frame

# Encode JPEG/PNG/WebP as base64 and put it in place of <BASE64>
curl -X POST https://bdkino.com/api/v1/identify \
  -H "Authorization: Bearer bdk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "image_base64": "<BASE64>",
    "lang": "en"
  }'

Response format

{
  "found": true,
  "source": "text",
  "request_id": "550e8400-e29b-41d4-a716-446655440000",
  "results": [
    {
      "id": 10681,
      "media_type": "movie",
      "title": "WALL·E",
      "year": 2008,
      "overview": "In the distant future, a small waste-collecting robot...",
      "poster_url": "https://bdkino.com/api/img/w500/hbhFnRzhIxs...",
      "blur_b64": "data:image/webp;base64,UklGRk...",
      "vote_average": 8.0,
      "vote_count": 19234,
      "popularity": 87.5,
      "confidence": 0.91,
      "genres":             ["Animation", "Family", "Sci-Fi"],
      "keywords":           ["robot", "earth", "garbage", "love"],
      "cast":               ["Ben Burtt", "Elissa Knight", "Jeff Garlin"],
      "directors":          ["Andrew Stanton"],
      "origin_country":     ["US"],
      "original_language":  "en",
      "tagline":            "An adventure beyond the ordinary world.",
      "runtime":            98,
      "age_rating":         "G",
      "collection_id":      null,
      "collection_name":    null
    }
  ],
  "fallback_url": "https://bdkino.com/search"
}

Field reference

FieldTypeDescription
foundbooleantrue if at least one result
sourcestringHow matched: "phash", "clip", "text" or "cinemind"
resultsarrayArray of matches (≤ 5), sorted by confidence DESC
idintegerMovie ID in bdkino database
media_typestring"movie" / "tv"
confidencefloat (0–1)Confidence: ≥ 0.85 — almost always correct
genresstring[]Genres in lang
keywordsstring[]Search tags
caststring[]Up to 10 cast (top-billed)
directorsstring[]Directors
taglinestring | nullTagline in lang
runtimeinteger | nullRuntime in minutes (movie only)
age_ratingstring | nullMPAA / TV-rating (US)
collection_idinteger | nullCollection ID if part of one
fallback_urlstringSearch page URL when found=false

Feedback: help train the AI

Each /v1/identify call returns a request_id in the response. Send it back with a vote (correct / wrong) — this goes into the Cinemind training set. A free feedback loop that improves accuracy for everyone.

POSThttps://bdkino.com/api/v1/identify/feedback

Request parameters

FieldTypeDescription
request_idUUIDFrom /v1/identify response (request_id field). Required.
vote"yes" | "no""yes" — correct match, "no" — wrong. Required.
idintegerID of specific result if response had multiple. Default — top.
media_type"movie" | "tv"Optional. Default from top.
commentstringOptional. Up to 300 chars. Reaches admin if vote=no.

Example

cURL
curl -X POST https://bdkino.com/api/v1/identify/feedback \
  -H "Authorization: Bearer bdk_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Accept-Language: en" \
  -d '{
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "vote": "yes",
    "id": 603,
    "media_type": "movie"
  }'

Response

{
  "ok": true,
  "vote": "yes",
  "training_pair_added": true,
  "message": "Thanks! Your vote helps train the AI."
}

💎 Why it matters

Every "correct" vote adds a positive training pair, every "wrong" — a negative one. After a few months these pairs go into Cinemind v2 fine-tune — the model becomes more accurate on your queries. Win-win.

Error codes

All errors return JSON of the form {"detail":"<error_code>"}.

200Success

Even when found=false this is still 200.

400provide_image_or_description / query_looks_invalid

No image and no description; invalid base64; or the description is gibberish.

401invalid_api_key

Key missing, doesn't exist or revoked.

402api_key_not_paid / api_key_expired

Key subscription is not paid or has expired. Activate/renew your plan in /developer.

403api_key_pending_activation

Key not yet activated / rejected by admin.

413image_too_large / description_too_long

image_too_large: image > 15 MB · description_too_long: description > 2000 chars.

429rate_limited

Hourly limit exceeded. Wait until the next hour and retry (exponential backoff).

5xxserver_error

Transient. Retry with exponential backoff.

Limits & behavior

Default rate limit120 req / hour / key
Image size≤ 15 MB
Description size3 – 2000 chars
Request timeout≤ 30 s (text) / ≤ 60 s (image)
Results per call≤ 5
Server-side response cachenone — cache on your side
Availability99.5 % monthly SLA

On 429, wait until the next hour and retry; client-side exponential backoff is recommended.

Best practices

Use exponential backoff

On 429 / 5xx wait 1s → 2s → 4s → 8s up to 60s. Don't retry 4xx (except 408/429).

Deduplicate requests

If your service can receive the same video twice — cache the response by hash(image)+description to save quota.

Compress images

1280×720 JPEG q=80 yields ~120 KB and accuracy on par with the original 4K. Resize before base64.

Check confidence

≥ 0.85 — show as a match. 0.55–0.85 — "could be:", let user confirm. < 0.55 — don't show.

Log on your side

Store the request_id from the response — helps support trace the issue faster.

Graceful degradation

If /v1/identify is unavailable — redirect to fallback_url (bdkino search page) and don't block UX.

Playground

Try it right here

Nothing to download: paste your key, type a scene description or upload a frame — and send the request straight from your browser. It hits the same domain, so it works with zero setup.

The key is stored only in this browser (localStorage) and sent directly to bdkino.

2000 chars

Prefer a desktop app or another tool? Alternatives below:

Python · Tkinter

bdkino API Tester (GUI)

Desktop GUI: JSON highlight, request history, key saving. Requires Python 3.10+ installed.

Download .zip (Python required)
Postman

Postman collection

Pre-built requests with env variables — import and test.

Download .json

Troubleshooting

PowerShell complains «Invoke-WebRequest: cannot find -X»
In PowerShell curl is an alias for Invoke-WebRequest with different parameters. Use curl.exe (with extension — invokes the real binary) or native Invoke-RestMethod. Line continuation in PowerShell is backtick `, not \. See the PowerShell tab above.
Getting 401 even though the key is copied in full
Check: 1) header is Authorization: Bearer <key> (not "Token" or just <key>); 2) key status in /developer is "active", not "pending"; 3) no whitespace before the key after copy-paste.
Returns 413 image_too_large
The limit is 15 MB on the file size itself (the server checks the decoded bytes, not the length of the base64 string). Resize to 1280×720 and compress JPEG quality 80.
found=true but results show the wrong movie
Check confidence: if < 0.7 the search is unsure (typically with cropped frames / low resolution / watermarks). Pass description alongside image_base64 — combining both dramatically improves accuracy.
Requests suddenly slow (>10 sec)
Model was unloaded from GPU and needs warm-up. First call after idle is 5–15 sec, subsequent ones are 200–800 ms. If high latency persists > 5 minutes — email support@bdkino.com.
How to test locally without burning quota?
Use the Playground GUI above — it shows quota usage in real time. Or enable client-side caching (Redis/LRU) — identical requests for the same image shouldn't hit the API.

Ready to start?

Submit a request in the developer dashboard — we'll get back within 24 hours for activation and payment.