# 发现 API

> discover 在 GET /3/discover/movie 列出电影，在 GET /3/discover/tv 列出剧集，可按类型、演员、公司、关键词、日期、评分、时长、语言和流媒体平台筛选与排序。JSON 与 TMDB v3 一致，缓存 30 分钟。

## 接口

`GET /3/discover/movie`

```bash
curl "https://api.amodb.dev/3/discover/movie?with_genres=878&sort_by=vote_average.desc&vote_count.gte=1000" \
  -H "Authorization: Bearer $AMODB_KEY"
```

响应:

```json
{
  "page": 1,
  "results": [
    {
      "adult": false,
      "backdrop_path": "/wLWvHcQz7N13DvSOTV7bHgwGXpT.jpg",
      "genre_ids": [
        878,
        12
      ],
      "id": 687163,
      "original_language": "en",
      "original_title": "Project Hail Mary",
      "overview": "Science teacher Ryland Grace wakes up on a spaceship light years from home with no recollection of who he is or how he got there. As his memory returns, he begins to uncover his mission: solve the riddle of the mysterious substance causing...",
      "popularity": 101.0341,
      "poster_path": "/yihdXomYb5kTeSivtFndMy5iDmf.jpg",
      "release_date": "2026-03-15",
      "title": "Project Hail Mary",
      "video": false,
      "vote_average": 8.635,
      "vote_count": 8355
    },
    {
      "adult": false,
      "backdrop_path": "/Ys8UIGWJpd2TMuQk8fU77W3mBz.jpg",
      "genre_ids": [
        12,
        18,
        878
      ],
      "id": 157336,
      "original_language": "en",
      "original_title": "Interstellar",
      "overview": "The adventures of a group of explorers who make use of a newly discovered wormhole to surpass the limitations on human space travel and conquer the vast distances involved in an interstellar voyage.",
      "popularity": 74.3949,
      "poster_path": "/yQvGrMoipbRoddT0ZR8tPoR7NfX.jpg",
      "release_date": "2014-11-04",
      "title": "Interstellar",
      "video": false,
      "vote_average": 8.491,
      "vote_count": 41529
    },
    {
      "adult": false,
      "backdrop_path": "/tanwf7KOwQ6dxZzehKsXkffIJOd.jpg",
      "genre_ids": [
        878,
        28,
        12
      ],
      "id": 969681,
      "original_language": "en",
      "original_title": "Spider-Man: Brand New Day",
      "overview": "Fighting crime full-time as Spider-Man in a world that doesn't remember him—and the pressure of seeing his old friends move on without him—sparks a change in Peter Parker he may not have the power to control. But that transformation might a...",
      "popularity": 663.5004,
      "poster_path": "/bjiS5ipwxb9JFy3XRRN4OAilSeX.jpg",
      "release_date": "2026-07-29",
      "title": "Spider-Man: Brand New Day",
      "video": false,
      "vote_average": 8.466,
      "vote_count": 5714
    }
  ],
  "total_pages": 39,
  "total_results": 772
}
```

## 发现电影

`GET /3/discover/movie` 返回一个分页的电影列表，这些电影匹配你发送的每个筛选条件，并按你选择的顺序排列。它是浏览页、“最佳”榜单和按维度推荐所用的接口，不需要 `query` 文本。如果你拿到的是用户输入的片名，请改用[搜索](https://amodb.dev/zh/search/)。

示例列出至少有 1000 票的科幻电影（类型 ID `878`），评分最高的在前。

```bash
curl -sSf --get "https://api.amodb.dev/3/discover/movie" \
  --data-urlencode "with_genres=878" \
  --data-urlencode "sort_by=vote_average.desc" \
  --data-urlencode "vote_count.gte=1000" \
  --data-urlencode "language=en-US" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```js
const params = new URLSearchParams({
  with_genres: '878',
  sort_by: 'vote_average.desc',
  'vote_count.gte': '1000',
  language: 'en-US',
});
const res = await fetch(`https://api.amodb.dev/3/discover/movie?${params}`, {
  headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` },
});
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { results, total_pages } = await res.json();
console.log(`page 1 of ${total_pages}`);
for (const m of results.slice(0, 5)) console.log(m.vote_average, m.title, m.release_date);
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/discover/movie",
    params={
        "with_genres": 878,
        "sort_by": "vote_average.desc",
        "vote_count.gte": 1000,
        "language": "en-US",
    },
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
data = r.json()
print("page 1 of", data["total_pages"])
for m in data["results"][:5]:
    print(m["vote_average"], m["title"], m["release_date"])
```

```php
<?php
$url = 'https://api.amodb.dev/3/discover/movie?' . http_build_query([
    'with_genres' => 878,
    'sort_by' => 'vote_average.desc',
    'vote_count.gte' => 1000,
    'language' => 'en-US',
]);
$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");
}
$data = json_decode($body, true);
foreach (array_slice($data['results'], 0, 5) as $m) {
    echo $m['vote_average'], ' ', $m['title'], PHP_EOL;
}
```

```go
package main

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

type Page struct {
	TotalPages int `json:"total_pages"`
	Results    []struct {
		Title       string  `json:"title"`
		ReleaseDate string  `json:"release_date"`
		VoteAverage float64 `json:"vote_average"`
	} `json:"results"`
}

func main() {
	q := url.Values{
		"with_genres":    {"878"},
		"sort_by":        {"vote_average.desc"},
		"vote_count.gte": {"1000"},
		"language":       {"en-US"},
	}
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/discover/movie?"+q.Encode(), 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 p Page
	if err := json.NewDecoder(res.Body).Decode(&p); err != nil {
		panic(err)
	}
	fmt.Println("pages:", p.TotalPages)
	for _, m := range p.Results {
		fmt.Println(m.VoteAverage, m.Title, m.ReleaseDate)
	}
}
```

### 参数

| 参数                                                    | 位置 | 必填  | 说明                                                                                                                                                                                                                               |
| ----------------------------------------------------- | -- | --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `api_key`                                             | 查询 | 二选一 | 你的密钥。使用它，或使用 `Authorization: Bearer` 请求头。                                                                                                                                                                                        |
| `sort_by`                                             | 查询 | 否   | 字段和方向，例如 `vote_average.desc`。字段有：`popularity`、`vote_average`、`vote_count`、`primary_release_date`、`revenue`、`title`、`original_title`，每个后面加 `.asc` 或 `.desc`。`title` 和 `original_title` 都按原始标题排序。未知的值回退到 `popularity.desc`，这也是默认值。 |
| `with_genres`                                         | 查询 | 否   | 类型 ID。逗号表示 AND，竖线字符表示 OR。                                                                                                                                                                                                        |
| `without_genres`                                      | 查询 | 否   | 要排除的类型 ID。                                                                                                                                                                                                                       |
| `with_cast`、`with_crew`                               | 查询 | 否   | 人物 ID。用[搜索](https://amodb.dev/zh/search/)查找。                                                                                                                                                                                     |
| `with_people`                                         | 查询 | 否   | 以演员或幕后人员身份出现的人物 ID。                                                                                                                                                                                                              |
| `with_companies`、`without_companies`                  | 查询 | 否   | 要求或排除的制作公司 ID。逗号和竖线的用法与 `with_genres` 相同。                                                                                                                                                                                        |
| `with_keywords`、`without_keywords`                    | 查询 | 否   | 要求或排除的关键词 ID。见[关键词](https://amodb.dev/zh/keywords/)。                                                                                                                                                                             |
| `with_origin_country`                                 | 查询 | 否   | 大写的 2 位制作国家代码，例如 `FR`。                                                                                                                                                                                                           |
| `primary_release_year`                                | 查询 | 否   | 首次上映日期的四位年份。                                                                                                                                                                                                                     |
| `year`                                                | 查询 | 否   | 四位年份。匹配该年份内的任意上映日期，所以返回的作品比 `primary_release_year` 更多。                                                                                                                                                                           |
| `primary_release_date.gte`、`primary_release_date.lte` | 查询 | 否   | 首次上映日期的下限和上限，`YYYY-MM-DD`。                                                                                                                                                                                                       |
| `release_date.gte`、`release_date.lte`                 | 查询 | 否   | 任意国家任意上映日期的下限和上限，`YYYY-MM-DD`。                                                                                                                                                                                                   |
| `region`                                              | 查询 | 否   | 大写的 2 位国家代码。把每条结果中的 `release_date` 替换为该国家的日期。它不会移除作品。                                                                                                                                                                            |
| `certification_country`、`certification`               | 查询 | 否   | 年龄分级筛选，例如 `US` 和 `PG`。没有国家时会忽略 `certification`。`certification.gte` 和 `certification.lte` 给出范围。                                                                                                                                   |
| `vote_average.gte`、`vote_average.lte`                 | 查询 | 否   | 平均分的最小值和最大值，0 到 10。                                                                                                                                                                                                              |
| `vote_count.gte`、`vote_count.lte`                     | 查询 | 否   | 投票数的最小值和最大值。                                                                                                                                                                                                                     |
| `with_runtime.gte`、`with_runtime.lte`                 | 查询 | 否   | 时长的最小值和最大值，单位为分钟。                                                                                                                                                                                                                |
| `with_original_language`                              | 查询 | 否   | 原始语言，2 位代码，例如 `fr` 或 `ko`。                                                                                                                                                                                                       |
| `with_watch_providers`                                | 查询 | 否   | 平台 ID。需要 `watch_region`，没有它则被忽略。ID 来自[类型与查找列表](https://amodb.dev/zh/genres/)。                                                                                                                                                    |
| `watch_region`                                        | 查询 | 否   | 用于平台可用性的大写 2 位国家代码。                                                                                                                                                                                                              |
| `include_adult`                                       | 查询 | 否   | 接受但会被忽略。成人作品永远不会返回。                                                                                                                                                                                                              |
| `language`                                            | 查询 | 否   | `en-US` 或 `pl-PL` 这样的 TMDB 标签。提供 14 种基础语言。默认 `en-US`。                                                                                                                                                                            |
| `page`                                                | 查询 | 否   | 页码，1 到 500。默认 1。                                                                                                                                                                                                                 |

### 响应字段

| 字段                                       | 类型                | 说明                                                        |
| ---------------------------------------- | ----------------- | --------------------------------------------------------- |
| `page`、`total_pages`、`total_results`     | integer           | 这组筛选条件的分页信息。宽泛的筛选最多报告 1001 页和 20001 条结果，但只能读取第 1 到 500 页。 |
| `results`                                | array             | 最多 20 部电影。没有作品匹配全部筛选条件时为空。                                |
| `id`                                     | integer           | 用于[电影详情](https://amodb.dev/zh/movies/)的电影 ID。             |
| `title`、`original_title`、`overview`      | string            | 本地化文本和原始标题。                                               |
| `original_language`                      | string            | 电影制作所用语言的两位代码。                                            |
| `release_date`                           | string            | `YYYY-MM-DD`。                                             |
| `genre_ids`                              | array of integers | 只有 ID。用 `/genre/movie/list` 把它们映射为名称。                     |
| `poster_path`、`backdrop_path`            | string 或 null     | 拼接到 `https://img.amodb.dev/t/p/{size}`。                   |
| `vote_average`、`vote_count`、`popularity` | number            | 评分和排名数值。                                                  |
| `adult`、`video`                          | boolean           | `adult` 始终为 `false`。                                      |

### 示例响应

```json
{
  "page": 1,
  "results": [
    {
      "adult": false,
      "backdrop_path": "/wLWvHcQz7N13DvSOTV7bHgwGXpT.jpg",
      "genre_ids": [878, 12],
      "id": 687163,
      "original_language": "en",
      "original_title": "Project Hail Mary",
      "overview": "Science teacher Ryland Grace wakes up on a spaceship light years from home with no recollection of who he i...",
      "popularity": 101.0341,
      "poster_path": "/yihdXomYb5kTeSivtFndMy5iDmf.jpg",
      "release_date": "2026-03-15",
      "title": "Project Hail Mary",
      "video": false,
      "vote_average": 8.635,
      "vote_count": 8354
    },
    {
      "adult": false,
      "backdrop_path": "/Ys8UIGWJpd2TMuQk8fU77W3mBz.jpg",
      "genre_ids": [12, 18, 878],
      "id": 157336,
      "original_language": "en",
      "original_title": "Interstellar",
      "overview": "The adventures of a group of explorers who make use of a newly discovered wormhole to surpass the limitatio...",
      "popularity": 74.3949,
      "poster_path": "/yQvGrMoipbRoddT0ZR8tPoR7NfX.jpg",
      "release_date": "2014-11-04",
      "title": "Interstellar",
      "video": false,
      "vote_average": 8.491,
      "vote_count": 41526
    },
    {
      "adult": false,
      "backdrop_path": "/tanwf7KOwQ6dxZzehKsXkffIJOd.jpg",
      "genre_ids": [878, 28, 12],
      "id": 969681,
      "original_language": "en",
      "original_title": "Spider-Man: Brand New Day",
      "overview": "Fighting crime full-time as Spider-Man in a world that doesn't remember him...",
      "popularity": 663.5004,
      "poster_path": "/bjiS5ipwxb9JFy3XRRN4OAilSeX.jpg",
      "release_date": "2026-07-29",
      "title": "Spider-Man: Brand New Day",
      "video": false,
      "vote_average": 8.468,
      "vote_count": 5684
    }
  ],
  "total_pages": 39,
  "total_results": 772
}
```

该响应取自示例请求的实时 API。它被缩减为第 1 页 20 条中的 3 条，较长的 `overview` 字符串也已缩短。

## 组合筛选条件

不同参数之间以 AND 组合。在同一个参数内，逗号表示 AND，竖线字符表示 OR。在原始 URL 中竖线写作 `%7C`，会对查询值编码的客户端会替你完成。

| 目标           | 请求                                                                                        |
| ------------ | ----------------------------------------------------------------------------------------- |
| 票数足够的最佳科幻片   | `/discover/movie?with_genres=878&sort_by=vote_average.desc&vote_count.gte=1000`           |
| 动作或冒险        | `/discover/movie?with_genres=28%7C12`                                                     |
| 动作但不是动画      | `/discover/movie?with_genres=28&without_genres=16`                                        |
| 一位演员加一位导演    | `/discover/movie?with_cast=6193&with_crew=525`                                            |
| 某一年的长片       | `/discover/movie?primary_release_year=2010&with_runtime.gte=150`                          |
| 某个日期窗口内的上映作品 | `/discover/movie?primary_release_date.gte=2026-10-01&primary_release_date.lte=2026-10-31` |
| 某一种原始语言的电影   | `/discover/movie?with_original_language=fr`                                               |
| 在某国流媒体平台上    | `/discover/movie?with_watch_providers=8&watch_region=US`                                  |
| 美国 R 级       | `/discover/movie?certification_country=US&certification=R`                                |
| 排除某个关键词      | `/discover/movie?with_keywords=818&without_keywords=4565`                                 |

`with_original_language` 按作品制作时使用的语言筛选，它也接受 14 种提供的语言之外的代码，例如 `ja` 或 `ko`。返回文本的语言仍由 `language` 参数决定。在平台那一行中，`8` 是 Netflix。平台 ID 请从 `/watch/providers/movie` 读取。

## 发现电视剧

`GET /3/discover/tv` 使用相同的响应外壳和分页。条目包含 `name`、`original_name`、`first_air_date`、`origin_country` 和 `genre_ids`，类型 ID 来自 `/genre/tv/list`，其中包含合并后的电视类型 ID，例如科幻与奇幻的 `10765`。

| 参数                                                                                                 | 说明                                                                                                                                           |
| -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `first_air_date.gte`、`first_air_date.lte`                                                          | 首播日期的下限和上限，`YYYY-MM-DD`。                                                                                                                     |
| `first_air_date_year`                                                                              | 首播日期的四位年份。                                                                                                                                   |
| `air_date.gte`、`air_date.lte`                                                                      | 剧集有集数播出的日期的下限和上限，`YYYY-MM-DD`。                                                                                                               |
| `with_networks`                                                                                    | 电视网 ID。在[公司与电视网](https://amodb.dev/zh/companies-networks/)页查找。                                                                               |
| `with_status`                                                                                      | 数字状态码：`0` 连载中，`2` 制作中，`3` 已完结，`4` 已取消。                                                                                                       |
| `with_type`                                                                                        | 数字节目类型：`0` 纪录片，`1` 新闻，`2` 迷你剧，`3` 真人秀，`4` 剧本剧，`5` 脱口秀，`6` 视频。                                                                                |
| `sort_by`                                                                                          | `popularity`、`vote_average`、`vote_count`、`first_air_date`、`name` 或 `original_name`，每个后面加 `.asc` 或 `.desc`。`name` 和 `original_name` 都按原始名称排序。 |
| `with_genres`、`without_genres`、`with_companies`、`with_keywords`、`without_keywords`                 | 规则与电影相同。                                                                                                                                     |
| `vote_average.gte`、`vote_count.gte`、`with_runtime.gte`、`with_runtime.lte`、`with_original_language` | 规则与电影相同。                                                                                                                                     |
| `with_watch_providers`、`watch_region`、`language`、`page`                                            | 规则与电影相同。                                                                                                                                     |

像 `/discover/tv?first_air_date.gte=2025-01-01&with_genres=18&vote_count.gte=100&sort_by=popularity.desc` 这样的请求，会列出 2025 年或更晚开播的剧情类剧集。结果的详细读取见[电视剧](https://amodb.dev/zh/tv-series/)。

## 错误

| HTTP | status_code | 何时出现                          |
| ---- | ----------- | ----------------------------- |
| 401  | 7           | 密钥缺失或错误。                      |
| 402  | 36          | 套餐周期已结束。                      |
| 405  | 37          | 你调用了写入方法。                     |
| 429  | 25          | 超过每分钟请求数。请等待 `Retry-After` 秒。 |
| 500  | 11          | `page` 超出 1 到 500。            |
| 504  | 24          | 后端未能及时响应。请重试一次。               |

没有任何匹配的筛选组合不算错误。你会得到 HTTP 200，`results` 为空数组，`total_results` 为 0。见[错误](https://amodb.dev/zh/errors/)和[速率限制](https://amodb.dev/zh/rate-limits/)。

## 实用说明

- 边缘节点把每组不同的筛选条件缓存 30 分钟，并在各密钥之间共享。缓存键使用排序后的查询，所以参数的顺序无关紧要。
- 每页 20 条，最后一页是 500，所以一组筛选条件最多取到 10,000 条。要更深入，请按日期窗口切分。宽泛的筛选会报告 `total_results` 为 20001，这是上限而不是真实数量。
- 请始终把 `sort_by=vote_average.desc` 与 `vote_count.gte` 搭配使用。否则，只有几票的作品会挤满榜首。
- 筛选条件中的 ID 都是数字。人物 ID 从[搜索](https://amodb.dev/zh/search/)获取，类型和平台 ID 从[类型与查找列表](https://amodb.dev/zh/genres/)获取。
- 想要现成的列表，例如热门或正在上映，请见[热门趋势与列表](https://amodb.dev/zh/trending-lists/)。

## 常见问题

### discover 结果最多能翻多深？

page 参数范围为 1 到 500，每页 20 条，所以一组筛选条件最多取到 10,000 条。要读取更多，请用 primary_release_date.gte 和 .lte 把查询切成日期窗口。

### 如何用 AND 和 OR 组合类型？

在同一个参数内，逗号表示 AND，竖线字符表示 OR。竖线在原始 URL 中写作 %7C。不同参数之间始终是 AND。

### 为什么按评分排序会返回冷门作品？

只有寥寥几票却全是满分的作品会排在榜首。请加上 vote_count.gte，例如 1000，这样只有票数足够的作品才会按 vote_average 排名。

### discover 结果有多新？

边缘节点把每组不同的筛选条件缓存 30 分钟，并在各密钥之间共享。每次调用仍然计入你的每分钟请求数，因为速率限制先于缓存执行。

## 相关页面

- [搜索 API](https://amodb.dev/zh/search/): 路径和 JSON 与 TMDB v3 相同的搜索 API。按文本查找电影、电视剧、人物、系列合集、公司和关键词，支持年份筛选和分页。
- [类型与查找列表](https://amodb.dev/zh/genres/): 采用 TMDB v3 路径的类型列表 API：带译名的电影和电视剧类型 ID，以及国家、语言、职务、年龄分级和流媒体平台列表。
- [热门与榜单接口](https://amodb.dev/zh/trending-lists/): 兼容 TMDB v3 路径的热门电影 API：日榜与周榜，以及电影和电视剧的正在上映、热门、高分、即将上映榜单，缓存 30 分钟。
- [关键词 API](https://amodb.dev/zh/keywords/): 采用 TMDB v3 路径的关键词 API：列出电影或剧集的情节标签、查询关键词及其电影，并把 ID 用于 discover 的 with_keywords。
- [公司与电视网](https://amodb.dev/zh/companies-networks/): 按 TMDB v3 路径查询制作公司和电视网：按 ID 读取名称、国家和标志，再按公司或电视网 ID 筛选 discover。
- [速率限制](https://amodb.dev/zh/rate-limits/): amodb 按滑动 60 秒窗口内每分钟请求数限制每个密钥：按套餐为 20、40 或 120。读取速率限制响应头，并用 Retry-After 处理 429。

更新于: 2026-10-18. Source: https://amodb.dev/zh/discover/
