# Program de proiecții în cinema

> GET /3/movie/{movie_id}/showtimes?country=RU întoarce cinematografele care proiectează un film într-o țară, cu proiecții datate la fiecare. Fără country întoarce doar totaluri pe țară într-o listă countries. Acoperirea variază după țară și titlu, iar un array results gol înseamnă că nu se știe nimic pentru acea pereche.

## Endpoint

`GET /3/movie/{movie_id}/showtimes`

```bash
curl "https://api.amodb.dev/3/movie/550/showtimes?country=RU" \
  -H "Authorization: Bearer $AMODB_KEY"
```

Răspuns:

```json
{
  "id": 550,
  "country": "RU",
  "results": [
    {
      "id": 1114,
      "name": "Мираж Синема НА БОЛЬШОМ",
      "chain": {
        "key": "mirage-ru",
        "name": "Мираж Синема"
      },
      "city": "Санкт-Петербург",
      "region": null,
      "address": "Большой пр. П.С., д. 35А",
      "postal_code": null,
      "country": "RU",
      "timezone": "Europe/Moscow",
      "latitude": null,
      "longitude": null,
      "phone": null,
      "url": "https://www.mirage.ru/spb/cinema/1/",
      "showtimes": [
        {
          "date": "2026-10-18",
          "start": "2026-10-18T21:40",
          "end": null,
          "auditorium": null,
          "formats": [
            "2D"
          ],
          "tags": [],
          "audio": null,
          "subtitles": null,
          "language": null,
          "price": null,
          "currency": null,
          "prices": null,
          "booking_url": "https://www.mirage.ru/ticket_new/aca7b114-d587-4fc5-9df6-28568e8fa9b3/",
          "sold_out": false
        },
        {
          "date": "2026-10-19",
          "start": "2026-10-19T22:20",
          "end": null,
          "auditorium": "Зал №4",
          "formats": [
            "2D"
          ],
          "tags": [],
          "audio": null,
          "subtitles": null,
          "language": null,
          "price": null,
          "currency": null,
          "prices": null,
          "booking_url": "https://www.mirage.ru/ticket_new/0c32e190-890a-4c81-a754-3300fefc4d5e/",
          "sold_out": false
        },
        {
          "date": "2026-10-20",
          "start": "2026-10-20T21:40",
          "end": null,
          "auditorium": null,
          "formats": [
            "2D"
          ],
          "tags": [],
          "audio": null,
          "subtitles": null,
          "language": null,
          "price": null,
          "currency": null,
          "prices": null,
          "booking_url": "https://www.mirage.ru/ticket_new/7f18e423-4a40-40f3-b68f-8664f4e3fa75/",
          "sold_out": false
        }
      ]
    },
    {
      "id": 1115,
      "name": "Мираж Синема ПИК",
      "chain": {
        "key": "mirage-ru",
        "name": "Мираж Синема"
      },
      "city": "Санкт-Петербург",
      "region": null,
      "address": "ул. Ефимова, д.2",
      "postal_code": null,
      "country": "RU",
      "timezone": "Europe/Moscow",
      "latitude": null,
      "longitude": null,
      "phone": null,
      "url": "https://www.mirage.ru/spb/cinema/27/",
      "showtimes": [
        {
          "date": "2026-10-19",
          "start": "2026-10-19T20:10",
          "end": null,
          "auditorium": "Зал №4",
          "formats": [
            "2D"
          ],
          "tags": [],
          "audio": null,
          "subtitles": null,
          "language": null,
          "price": null,
          "currency": null,
          "prices": null,
          "booking_url": "https://www.mirage.ru/ticket_new/1d143ca6-1bbe-48ee-954a-063b6088a32a/",
          "sold_out": false
        },
        {
          "date": "2026-10-20",
          "start": "2026-10-20T20:10",
          "end": null,
          "auditorium": "Зал №4",
          "formats": [
            "2D"
          ],
          "tags": [],
          "audio": null,
          "subtitles": null,
          "language": null,
          "price": null,
          "currency": null,
          "prices": null,
          "booking_url": "https://www.mirage.ru/ticket_new/8b2e0f6a-5b62-41eb-a398-1b709539f03d/",
          "sold_out": false
        },
        {
          "date": "2026-10-21",
          "start": "2026-10-21T20:10",
          "end": null,
          "auditorium": "Зал №4",
          "formats": [
            "2D"
          ],
          "tags": [],
          "audio": null,
          "subtitles": null,
          "language": null,
          "price": null,
          "currency": null,
          "prices": null,
          "booking_url": "https://www.mirage.ru/ticket_new/3723875b-a7df-426f-968a-4bdaa1a8bdd7/",
          "sold_out": false
        }
      ]
    }
  ],
  "countries": [
    {
      "country": "RU",
      "name": "Russia",
      "venues": 2,
      "cities": 1,
      "showtimes": 6,
      "first_day": "2026-10-19",
      "last_day": "2026-10-21"
    }
  ]
}
```

## Obține programul de proiecții al unui film

`GET /3/movie/{movie_id}/showtimes?country=RU` întoarce cinematografele care proiectează un film într-o țară, cu proiecțiile datate de la fiecare. Parametrul `country` primește un cod de două litere, cu litere mari sau mici. Acoperirea variază după țară și titlu, deci datele sunt prezente acolo unde se cunosc și lipsesc unde nu. Se întorc doar zilele de azi încolo.

Exemplul cere Fight Club în Rusia și tratează un răspuns gol.

```bash
curl -sf "https://api.amodb.dev/3/movie/550/showtimes?country=RU" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```js
const url = 'https://api.amodb.dev/3/movie/550/showtimes?country=RU';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const data = await res.json();
if (data.results.length === 0) console.log('no showtimes known');
for (const venue of data.results) {
  for (const s of venue.showtimes) {
    console.log(venue.name, venue.city, s.start, s.formats.join(','), s.booking_url);
  }
}
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/550/showtimes",
    params={"country": "RU"},
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
results = r.json()["results"]
if not results:
    print("no showtimes known")
for venue in results:
    for s in venue["showtimes"]:
        print(venue["name"], venue["city"], s["start"], ",".join(s["formats"]))
```

```php
<?php
$url = 'https://api.amodb.dev/3/movie/550/showtimes?country=RU';
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 10,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AMODB_KEY')],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
    throw new RuntimeException("amodb returned $status");
}
$results = json_decode($body, true)['results'];
if (!$results) {
    echo 'no showtimes known', PHP_EOL;
}
foreach ($results as $venue) {
    foreach ($venue['showtimes'] as $s) {
        echo $venue['name'], ' ', $s['start'], ' ', implode(',', $s['formats']), PHP_EOL;
    }
}
```

```go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strings"
	"time"
)

type Venue struct {
	Name      string `json:"name"`
	City      string `json:"city"`
	Showtimes []struct {
		Start      string   `json:"start"`
		Formats    []string `json:"formats"`
		BookingURL string   `json:"booking_url"`
	} `json:"showtimes"`
}

func main() {
	url := "https://api.amodb.dev/3/movie/550/showtimes?country=RU"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
	client := &http.Client{Timeout: 10 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		panic(res.Status)
	}
	var body struct {
		Results []Venue `json:"results"`
	}
	if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
		panic(err)
	}
	if len(body.Results) == 0 {
		fmt.Println("no showtimes known")
	}
	for _, v := range body.Results {
		for _, s := range v.Showtimes {
			fmt.Println(v.Name, v.City, s.Start, strings.Join(s.Formats, ","))
		}
	}
}
```

### Parametri

| Parametru  | Loc        | Obligatoriu          | Descriere                                                                                                  |
| ---------- | ---------- | -------------------- | ---------------------------------------------------------------------------------------------------------- |
| `movie_id` | cale       | da                   | ID numeric de film, de exemplu `550`.                                                                      |
| `country`  | interogare | nu                   | Cod de țară din două litere, precum `RU`. Fără el primești doar rezumatul pe țări. `region` este un alias. |
| `api_key`  | interogare | una dintre cele două | Cheia ta. Folosește-o pe aceasta sau antetul `Authorization: Bearer`.                                      |

### Câmpurile răspunsului

| Câmp                                                   | Tip             | Observații                                                                                                                                         |
| ------------------------------------------------------ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                                                   | număr întreg    | ID-ul filmului.                                                                                                                                    |
| `country`                                              | șir sau null    | Codul cu litere mari pe care l-ai cerut sau `null` când `country` lipsește sau nu are două litere.                                                 |
| `results`                                              | array           | Un obiect pe cinematograf, ordonat după cinematograf. Gol când nu se știe nimic sau nu s-a trimis nicio țară. Cel mult 1500 de proiecții în total. |
| `results[].id`                                         | număr întreg    | ID-ul cinematografului.                                                                                                                            |
| `results[].name`                                       | șir             | Numele cinematografului.                                                                                                                           |
| `results[].chain`                                      | obiect          | `key` este cheia lanțului, `name` este numele lanțului sau `null`.                                                                                 |
| `results[].city`                                       | șir sau null    | Orașul.                                                                                                                                            |
| `results[].region`                                     | șir sau null    | Regiunea.                                                                                                                                          |
| `results[].address`                                    | șir sau null    | Adresa stradală.                                                                                                                                   |
| `results[].postal_code`                                | șir sau null    | Codul poștal.                                                                                                                                      |
| `results[].country`                                    | șir             | Codul de țară al cinematografului.                                                                                                                 |
| `results[].timezone`                                   | șir sau null    | Fus orar IANA precum `Europe/Moscow`.                                                                                                              |
| `results[].latitude`, `results[].longitude`            | număr sau null  | Poziția cinematografului.                                                                                                                          |
| `results[].phone`                                      | șir sau null    | Număr de telefon.                                                                                                                                  |
| `results[].url`                                        | șir sau null    | Pagina cinematografului.                                                                                                                           |
| `results[].showtimes`                                  | array           | Proiecțiile de la acel cinematograf, ordonate după început.                                                                                        |
| `results[].showtimes[].date`                           | șir             | Ziua ca `2026-10-18`.                                                                                                                              |
| `results[].showtimes[].start`                          | șir             | Începutul în ora locală a cinematografului, precum `2026-10-18T21:40`, fără decalaj UTC.                                                           |
| `results[].showtimes[].end`                            | șir sau null    | Sfârșitul în ora locală a cinematografului.                                                                                                        |
| `results[].showtimes[].auditorium`                     | șir sau null    | Numele sălii.                                                                                                                                      |
| `results[].showtimes[].formats`                        | array de șiruri | Formate precum `2D`.                                                                                                                               |
| `results[].showtimes[].tags`                           | array de șiruri | Etichete suplimentare. Adesea gol.                                                                                                                 |
| `results[].showtimes[].audio`, `subtitles`, `language` | șir sau null    | Detalii despre sunet, subtitrări și limbă când se cunosc.                                                                                          |
| `results[].showtimes[].price`                          | număr sau null  | Prețul biletului.                                                                                                                                  |
| `results[].showtimes[].currency`                       | șir sau null    | Moneda lui `price`.                                                                                                                                |
| `results[].showtimes[].prices`                         | orice sau null  | Detalii de preț când un cinematograf are mai multe.                                                                                                |
| `results[].showtimes[].booking_url`                    | șir sau null    | Link pentru rezervarea locului.                                                                                                                    |
| `results[].showtimes[].sold_out`                       | boolean         | `true` când proiecția este epuizată.                                                                                                               |
| `countries`                                            | array           | Rezumat pe țări, vezi mai jos.                                                                                                                     |

Citește după nume cheile pe care le folosești și sari peste cheile suplimentare dintr-un obiect de cinematograf sau de proiecție. Multe câmpuri sunt azi `null`, pentru că nu toate cinematografele le trimit.

### Exemplu de răspuns

```json
{
  "id": 550,
  "country": "RU",
  "results": [
    {
      "id": 1114,
      "name": "Мираж Синема НА БОЛЬШОМ",
      "chain": {
        "key": "mirage-ru",
        "name": "Мираж Синема"
      },
      "city": "Санкт-Петербург",
      "region": null,
      "address": "Большой пр. П.С., д. 35А",
      "postal_code": null,
      "country": "RU",
      "timezone": "Europe/Moscow",
      "latitude": null,
      "longitude": null,
      "phone": null,
      "url": "https://www.mirage.ru/spb/cinema/1/",
      "showtimes": [
        {
          "date": "2026-10-18",
          "start": "2026-10-18T21:40",
          "end": null,
          "auditorium": null,
          "formats": ["2D"],
          "tags": [],
          "audio": null,
          "subtitles": null,
          "language": null,
          "price": null,
          "currency": null,
          "prices": null,
          "booking_url": "https://www.mirage.ru/ticket_new/aca7b114-d587-4fc5-9df6-28568e8fa9b3/",
          "sold_out": false
        },
        {
          "date": "2026-10-19",
          "start": "2026-10-19T22:20",
          "end": null,
          "auditorium": "Зал №4",
          "formats": ["2D"],
          "tags": [],
          "audio": null,
          "subtitles": null,
          "language": null,
          "price": null,
          "currency": null,
          "prices": null,
          "booking_url": "https://www.mirage.ru/ticket_new/0c32e190-890a-4c81-a754-3300fefc4d5e/",
          "sold_out": false
        }
      ]
    }
  ],
  "countries": [
    {
      "country": "RU",
      "name": "Russia",
      "venues": 2,
      "cities": 1,
      "showtimes": 7,
      "first_day": "2026-10-18",
      "last_day": "2026-10-21"
    }
  ]
}
```

Lista este tăiată la 1 din 2 cinematografe și 2 din 4 proiecții. Proiecțiile există doar pentru zilele care nu au trecut, deci acest răspuns se schimbă în fiecare zi.

## Obține rezumatul pe țări

Lasă deoparte `country` și răspunsul conține doar totaluri. `results` rămâne gol, iar `country` este `null`. Array-ul `countries` listează până la 60 de țări care mai au o proiecție, cea cu cele mai multe proiecții prima. Folosește-l ca să afli unde rulează un titlu înainte să ceri cinematografele.

```bash
curl -sf "https://api.amodb.dev/3/movie/550/showtimes" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```json
{
  "id": 550,
  "country": null,
  "results": [],
  "countries": [
    {
      "country": "RU",
      "name": "Russia",
      "venues": 2,
      "cities": 1,
      "showtimes": 7,
      "first_day": "2026-10-18",
      "last_day": "2026-10-21"
    }
  ]
}
```

| Câmp                                            | Tip          | Observații                                                   |
| ----------------------------------------------- | ------------ | ------------------------------------------------------------ |
| `countries[].country`                           | șir          | Cod din două litere, gata de folosit ca parametru `country`. |
| `countries[].name`                              | șir          | Numele țării în engleză.                                     |
| `countries[].venues`                            | număr întreg | Cinematografe cu o proiecție.                                |
| `countries[].cities`                            | număr întreg | Orașe cu o proiecție.                                        |
| `countries[].showtimes`                         | număr întreg | Proiecții de azi încolo.                                     |
| `countries[].first_day`, `countries[].last_day` | șir          | Prima și ultima zi cu o proiecție.                           |

Un cod de țară fără date, precum `country=US` pentru acest film, răspunde cu `country` ca `US`, un `results` gol și aceeași listă `countries`. Un titlu fără proiecții nicăieri, precum serialul 1396, are `"countries": []`.

## Adaugă programul la un apel de detalii

`append_to_response=showtimes` îmbină același bloc într-un răspuns de detalii sub cheia `showtimes`. Trimite codul `country` în aceeași cerere. Blocul își păstrează propriile chei `id`, `country`, `results` și `countries`.

| Cerere                                                         | Rezultat                                            |
| -------------------------------------------------------------- | --------------------------------------------------- |
| `/3/movie/550?append_to_response=showtimes&country=RU`         | Fișa filmului plus un bloc `showtimes` pentru Rusia |
| `/3/movie/550?append_to_response=credits,showtimes&country=RU` | Adaugă credite în același apel                      |

Se numără ca o singură cerere, deci o pagină de film care arată distribuția și proiecțiile are nevoie de un singur apel. Același endpoint există pentru seriale ca `GET /3/tv/{tv_id}/showtimes`.

## Combină cu now_playing și region

Lista now playing îți dă titlurile. Endpoint-ul de program îți dă proiecțiile pentru un singur titlu. Îmbină-le în codul tău.

| Pas | Cerere                                                     | Rezultat                                             |
| --- | ---------------------------------------------------------- | ---------------------------------------------------- |
| 1   | `GET /3/movie/now_playing?region=RU&page=1`                | Până la 20 de filme pe pagină, în cache 30 de minute |
| 2   | `GET /3/movie/{id}/showtimes?country=RU` pentru fiecare ID | Cinematografe și ore, unde se știu                   |

Bucla de mai jos reîncearcă o dată sau de două ori când se atinge limita planului, așteptând numărul de secunde din `Retry-After`.

```js
const base = 'https://api.amodb.dev/3';
const headers = { Authorization: `Bearer ${process.env.AMODB_KEY}` };

async function get(path, retries = 2) {
  const res = await fetch(base + path, { headers });
  if (res.status === 429 && retries > 0) {
    const wait = Number(res.headers.get('Retry-After') ?? 60);
    await new Promise((resolve) => setTimeout(resolve, wait * 1000));
    return get(path, retries - 1);
  }
  if (!res.ok) throw new Error(`amodb returned ${res.status} for ${path}`);
  return res.json();
}

const playing = await get('/movie/now_playing?region=RU&page=1');
for (const movie of playing.results) {
  const data = await get(`/movie/${movie.id}/showtimes?country=RU`);
  if (data.results.length > 0) console.log(movie.title, data.results.length, 'venues');
}
```

O pagină de 20 de titluri înseamnă 20 de cereri de program. Pe planul de 20 de cereri pe minut asta folosește toată fereastra, deci pune rezultatul în cache la tine. Vezi [tendințe și liste](https://amodb.dev/ro/trending-lists/) pentru parametrii listei.

## Erori

Corpul de eroare urmează TMDB: `success`, `status_code` și `status_message`. O cheie greșită arată `status_code` 7.

| HTTP | status_code | Când                                                                         |
| ---- | ----------- | ---------------------------------------------------------------------------- |
| 401  | 7           | Cheia lipsește sau este greșită.                                             |
| 402  | 36          | Perioada planului s-a încheiat.                                              |
| 404  | 34          | Niciun film cu acel ID.                                                      |
| 429  | 25          | Ai depășit cererile pe minut. Așteaptă numărul de secunde din `Retry-After`. |

Lipsa programului nu este o eroare: așteaptă-te la starea 200 și un array `results` gol. Nici un `country` lipsă sau invalid nu este o eroare. Vezi [erori](https://amodb.dev/ro/errors/) și [limite de cereri](https://amodb.dev/ro/rate-limits/).

## Note practice

- Acoperirea variază după țară și titlu. Tratează un array `results` gol ca necunoscut, nu ca „nu rulează”.
- Arată `start` exact cum este întors. Este ora locală a cinematografului, fără decalaj UTC, iar ceasul cinematografului este ceea ce se așteaptă vizitatorii.
- Programul este ținut în cache la margine 30 de minute. Nu-l cere la fiecare afișare de pagină și ține-ți propriul cache scurt.
- Reutilizează o singură listă now playing pentru toți vizitatorii dintr-o regiune. Este ținută în cache 30 de minute și la margine.
- Folosește `booking_url` ca să trimiți un vizitator la pagina de rezervare a cinematografului. Este `null` când cinematograful nu dă niciun link.
- Pentru prezentarea cazului de utilizare, vezi [API pentru program cinema](https://amodb.dev/ro/cinema-showtimes-api/), iar pentru celelalte date despre un film, vezi [filme](https://amodb.dev/ro/movies/).

## Întrebări și răspunsuri

### Este obligatoriu parametrul country?

Nu, dar ai nevoie de el ca să primești cinematografele. Trimite un cod de două litere, precum RU sau DE. Fără country, sau cu un cod care nu are două litere, results este gol, iar lista countries arată unde există proiecții. Parametrul region funcționează ca alias.

### Ce înseamnă un array results gol?

Înseamnă că nu se cunosc proiecții pentru acel titlu în acea țară de azi încolo. Nu dovedește că filmul nu rulează. Lista countries arată în continuare alte țări cu date. Oferă în schimb data lansării din detaliile filmului.

### Cum găsesc filmele care rulează acum în cinematografe?

Apelează GET /3/movie/now_playing cu parametrul region, apoi cere programul pentru ID-urile care te interesează. Lista este ținută în cache 30 de minute, deci o poți reutiliza pentru fiecare vizitator.

### Sunt orele în fusul orar al vizitatorului meu?

Nu. Valoarea start este ora locală de la cinematograf și nu are decalaj UTC. Fiecare cinematograf are și un timezone precum Europe/Moscow. Arată start așa cum este întors și nu-l converti cu fusul orar al vizitatorului.

## Pagini conexe

- [API pentru program cinema](https://amodb.dev/ro/cinema-showtimes-api/): API pentru program cinema: GET /3/movie/{movie_id}/showtimes cu cod de țară întoarce cinematografe, ore și formate, unde se știu. Combină-l cu now_playing.
- [Endpoint-uri pentru tendințe și liste](https://amodb.dev/ro/trending-lists/): API filme în tendințe cu căi TMDB v3: topuri pe zi și săptămână, plus now playing, populare, bine cotate și viitoare pentru filme și TV, în cache 30 de minute.
- [API detalii film](https://amodb.dev/ro/movies/): API detalii film cu aceleași căi și același JSON ca TMDB v3. Preia un film după ID, adaugă credite, evaluări și atmosferă cu append_to_response, în 14 limbi.
- [Evaluări pentru filme și TV](https://amodb.dev/ro/ratings/): API evaluări filme ce întoarce scorurile IMDb, Kinopoisk, Metacritic, Rotten Tomatoes și TMDB pentru un titlu într-un apel, cu null pentru sursele necunoscute.
- [Limite de cereri](https://amodb.dev/ro/rate-limits/): amodb limitează fiecare cheie în cereri pe minut, în fereastră glisantă de 60 de secunde: 20, 40 sau 120. Citește antetele și tratează 429 cu Retry-After.
- [Ghid rapid](https://amodb.dev/ro/quickstart/): Fă primul apel amodb: ia o cheie, cere detaliile unui film în curl, JavaScript, Python, PHP sau Go, apoi încarcă posterul de pe img.amodb.dev. Sub 2 minute.

Actualizat: 2026-10-18. Source: https://amodb.dev/ro/showtimes/
