# 按外部 ID 查找

> find 接口把 IMDb、TVDB、Wikidata、Kinopoisk 等外部 ID 转为 TMDB 风格结果，external_ids 接口则反向查询。Wikidata 接口补充预算、票房、奖项和关联作品，全部使用普通密钥。

## 接口

`GET /3/find/{external_id}`

```bash
curl "https://api.amodb.dev/3/find/tt0137523?external_source=imdb_id" \
  -H "Authorization: Bearer $AMODB_KEY"
```

响应:

```json
{
  "movie_results": [
    {
      "adult": false,
      "backdrop_path": "/c6OLXfKAk5BKeR6broC8pYiCquX.jpg",
      "genre_ids": [
        18,
        53
      ],
      "id": 550,
      "original_language": "en",
      "original_title": "Fight Club",
      "overview": "A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy. Their concept catches on, with underground \"fight clubs\" forming in every town, until an eccentric gets in the wa...",
      "popularity": 39.0054,
      "poster_path": "/jSziioSwPVrOy9Yow3XhWIBDjq1.jpg",
      "release_date": "1999-10-15",
      "title": "Fight Club",
      "video": false,
      "vote_average": 8.437,
      "vote_count": 33042,
      "media_type": "movie"
    }
  ],
  "person_results": [],
  "tv_results": [],
  "tv_episode_results": [],
  "tv_season_results": []
}
```

## 按外部 ID 查找作品

`GET /3/find/{external_id}` 接受另一个系统的 ID 并返回匹配的记录。路径中是 ID，`external_source` 查询参数说明它来自哪个系统。amodb 接受十二种来源，其中七种能解析为记录：`imdb_id`、`tvdb_id`、`wikidata_id`、`kinopoisk_id`、`facebook_id`、`twitter_id` 和 `instagram_id`。

示例把 IMDb ID `tt0137523` 映射为 TMDB ID。

```bash
curl -sf "https://api.amodb.dev/3/find/tt0137523?external_source=imdb_id" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```js
const url = 'https://api.amodb.dev/3/find/tt0137523?external_source=imdb_id';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const found = await res.json();
const movie = found.movie_results[0];
console.log(movie ? `${movie.id} ${movie.title}` : 'no match');
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/find/tt0137523",
    params={"external_source": "imdb_id"},
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
results = r.json()["movie_results"]
print(f"{results[0]['id']} {results[0]['title']}" if results else "no match")
```

```php
<?php
$url = 'https://api.amodb.dev/3/find/tt0137523?external_source=imdb_id';
$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");
}
$movies = json_decode($body, true)['movie_results'];
echo $movies ? $movies[0]['id'] . ' ' . $movies[0]['title'] : 'no match', PHP_EOL;
```

```go
package main

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

type Found struct {
	MovieResults []struct {
		ID    int    `json:"id"`
		Title string `json:"title"`
	} `json:"movie_results"`
}

func main() {
	url := "https://api.amodb.dev/3/find/tt0137523?external_source=imdb_id"
	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 f Found
	if err := json.NewDecoder(res.Body).Decode(&f); err != nil {
		panic(err)
	}
	if len(f.MovieResults) == 0 {
		fmt.Println("no match")
		return
	}
	fmt.Println(f.MovieResults[0].ID, f.MovieResults[0].Title)
}
```

### 参数

| 参数                | 位置 | 必填  | 说明                                                                                                                                                                                |
| ----------------- | -- | --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `external_id`     | 路径 | 是   | 另一个系统中的 ID，例如 `tt0137523`。                                                                                                                                                        |
| `external_source` | 查询 | 是   | `imdb_id`、`tvdb_id`、`wikidata_id`、`kinopoisk_id`、`facebook_id`、`twitter_id`、`instagram_id` 之一。另有五个也被接受但不返回任何内容：`freebase_mid`、`freebase_id`、`tvrage_id`、`tiktok_id`、`youtube_id`。 |
| `language`        | 查询 | 否   | 14 种语言之一，例如 `en` 或 `ru-RU`。其他值回退到 `en`。                                                                                                                                           |
| `api_key`         | 查询 | 二选一 | 你的密钥。使用它，或使用 `Authorization: Bearer` 请求头。                                                                                                                                         |

缺少 `external_source`，或它不在列表中，会返回 400 和 `status_code` 22。该值必须是小写。

### 响应字段

| 字段                   | 类型    | 说明                                                         |
| -------------------- | ----- | ---------------------------------------------------------- |
| `movie_results`      | array | 与搜索结果字段相同的电影记录，另有设为 `movie` 的 `media_type`。                |
| `person_results`     | array | 与该 ID 匹配的人物。每项的 `known_for` 为空数组，`media_type` 设为 `person`。 |
| `tv_results`         | array | 电视剧记录，`media_type` 设为 `tv`。                                |
| `tv_episode_results` | array | 始终为空。                                                      |
| `tv_season_results`  | array | 始终为空。                                                      |

### 示例响应

```json
{
  "movie_results": [
    {
      "adult": false,
      "backdrop_path": "/c6OLXfKAk5BKeR6broC8pYiCquX.jpg",
      "genre_ids": [18, 53],
      "id": 550,
      "original_language": "en",
      "original_title": "Fight Club",
      "overview": "A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking n...",
      "popularity": 39.0054,
      "poster_path": "/jSziioSwPVrOy9Yow3XhWIBDjq1.jpg",
      "release_date": "1999-10-15",
      "title": "Fight Club",
      "video": false,
      "vote_average": 8.437,
      "vote_count": 33039,
      "media_type": "movie"
    }
  ],
  "person_results": [],
  "tv_results": [],
  "tv_episode_results": [],
  "tv_season_results": []
}
```

简介已截断。

### 哪种来源能找到什么

| `external_source`                         | ID 的样子                    | 示例                                                  | 通常的结果数组                                         |
| ----------------------------------------- | ------------------------- | --------------------------------------------------- | ----------------------------------------------- |
| `imdb_id`                                 | 作品为 `tt` 加数字，人物为 `nm` 加数字 | `tt0137523`、`nm0000093`（布拉德·皮特）                     | `movie_results`、`tv_results` 或 `person_results` |
| `tvdb_id`                                 | 数字                        | `81189`（《绝命毒师》）                                     | `tv_results`                                    |
| `wikidata_id`                             | `Q` 加数字                   | `Q190050`（《搏击俱乐部》）、`Q1079`（《绝命毒师》）、`Q35332`（布拉德·皮特） | `movie_results`、`tv_results` 或 `person_results` |
| `kinopoisk_id`                            | 数字                        | `361`（《搏击俱乐部》）、`404900`（《绝命毒师》）                     | `movie_results` 或 `tv_results`                  |
| `facebook_id`、`twitter_id`、`instagram_id` | 账号名                       | `FightClub`                                         | 取决于账号                                           |

同一个账号名可能匹配多个作品。例如 `instagram_id=breakingbad` 会返回这部剧集和电影 El Camino，所以请读取每一个数组。

```bash
curl -sf "https://api.amodb.dev/3/find/361?external_source=kinopoisk_id" \
  -H "Authorization: Bearer $AMODB_KEY"
```

## 已知作品的外部 ID

反向查询是一组 `external_ids` 接口。它们为你已有的记录返回其他系统所使用的 ID。

| 方法和路径                                  | 返回内容                                                                                       | 参数          |
| -------------------------------------- | ------------------------------------------------------------------------------------------ | ----------- |
| `GET /movie/{movie_id}/external_ids`   | `imdb_id`、`wikidata_id`、`facebook_id`、`instagram_id`、`twitter_id`、`kinopoisk_id`           | `movie_id`  |
| `GET /tv/{tv_id}/external_ids`         | 同上，另加 `freebase_mid`、`freebase_id`、`tvdb_id`、`tvrage_id`                                   | `tv_id`     |
| `GET /person/{person_id}/external_ids` | `imdb_id`、`wikidata_id`、`facebook_id`、`instagram_id`、`tiktok_id`、`twitter_id`、`youtube_id` | `person_id` |

作品没有的 ID 会返回 `null`。`kinopoisk_id` 是字符串，只有在 amodb 知道时才会出现在电影或剧集上。`/3/movie/550/external_ids` 的真实返回：

```json
{
  "id": 550,
  "imdb_id": "tt0137523",
  "wikidata_id": "Q190050",
  "facebook_id": "FightClub",
  "instagram_id": null,
  "twitter_id": null,
  "kinopoisk_id": "361"
}
```

`/3/tv/1396/external_ids` 的真实返回：

```json
{
  "id": 1396,
  "imdb_id": "tt0903747",
  "freebase_mid": null,
  "freebase_id": null,
  "tvdb_id": 81189,
  "tvrage_id": null,
  "wikidata_id": "Q1079",
  "facebook_id": "BreakingBad",
  "instagram_id": "breakingbad",
  "twitter_id": "BreakingBad",
  "kinopoisk_id": "404900"
}
```

季和集的 `external_ids` 接口存在，但其中所有 ID 目前都是 `null`，所以请跳过它们。

## Wikidata 事实

`GET /3/movie/{movie_id}/wikidata` 和 `GET /3/tv/{tv_id}/wikidata` 返回作品的 Wikidata ID 及相关事实：金额、系列中的前后作品、维基百科页面、奖项和地点。每个键始终存在。未知的事实，单个值为 `null`，列表为 `[]`。

| 方法和路径                            | 返回内容                        | 参数                    |
| -------------------------------- | --------------------------- | --------------------- |
| `GET /movie/{movie_id}/wikidata` | Wikidata ID 和事实             | `movie_id`、`language` |
| `GET /tv/{tv_id}/wikidata`       | Wikidata ID 和事实             | `tv_id`、`language`    |
| `append_to_response=wikidata`    | `wikidata` 下的同一数据块，带有其 `id` | 加在详情调用上               |

这是《搏击俱乐部》（电影 550）的返回内容，已缩减到便于阅读的大小：

```json
{
  "id": 550,
  "wikidata_id": "Q190050",
  "budget": {
    "value": 63000000,
    "currency": "USD"
  },
  "box_office": {
    "value": 101209702,
    "currency": "USD",
    "worldwide": true
  },
  "follows": null,
  "followed_by": null,
  "sitelinks": {
    "en": "Fight Club",
    "ru": "Бойцовский клуб (фильм)",
    "uk": "Бійцівський клуб (фільм)"
  },
  "awards": [
    {
      "wikidata_id": "Q28044798",
      "label": "Empire Awards, UK for best british actress"
    },
    {
      "wikidata_id": "Q943908",
      "label": "Jupiter Award",
      "year": 2000
    }
  ],
  "nominations": [
    {
      "wikidata_id": "Q488645",
      "label": "Academy Award for Best Sound Editing",
      "year": 2000
    }
  ],
  "based_on": [
    {
      "wikidata_id": "Q837283",
      "label": "Fight Club",
      "author": {
        "wikidata_id": "Q268181",
        "label": "Chuck Palahniuk"
      }
    }
  ],
  "filming_locations": [
    {
      "wikidata_id": "Q65",
      "label": "Los Angeles"
    }
  ],
  "narrative_locations": [
    {
      "wikidata_id": "Q65",
      "label": "Los Angeles"
    }
  ],
  "original_broadcasters": []
}
```

`sitelinks` 对象有 14 项，`awards` 有 5 项。这里两者都已截断。

| 字段                                                                | 类型            | 说明                                                    |
| ----------------------------------------------------------------- | ------------- | ----------------------------------------------------- |
| `id`                                                              | integer       | 作品的 TMDB ID。使用 `append_to_response` 时它依然保留。           |
| `wikidata_id`                                                     | string 或 null | 形如 `Q190050` 的 Wikidata 条目。                           |
| `budget`                                                          | object 或 null | `value` 是取整后的整数，`currency` 是 ISO 代码或 `null`。          |
| `box_office`                                                      | object 或 null | 与 `budget` 相同，另有设为 `true` 或 `false` 的 `worldwide`。    |
| `follows`、`followed_by`                                           | object 或 null | 系列电影中的前一部和后一部作品，以链接形式给出。                              |
| `sitelinks`                                                       | object        | 把语言代码映射到维基百科页面标题。键是提供的 14 种语言。没有时为 `{}`。              |
| `awards`、`nominations`                                            | array         | 带有可选 `year` 的链接。                                      |
| `based_on`                                                        | array         | 原著作品，含 `wikidata_id`、`label` 和一个 `author` 对象或 `null`。 |
| `filming_locations`、`narrative_locations`、`original_broadcasters` | array         | 链接。《绝命毒师》的 `original_broadcasters` 中有 AMC。            |

链接包含 `wikidata_id`、`label`，当该条目是目录中的作品时，还有 `tmdb_id` 和 `media_type`。对于《黑客帝国：重装上阵》（电影 604），前后作品是指向电影 603 和 605 的链接：

```json
{
  "follows": {
    "wikidata_id": "Q83495",
    "label": "The Matrix",
    "tmdb_id": 603,
    "media_type": "movie"
  },
  "followed_by": {
    "wikidata_id": "Q207536",
    "label": "The Matrix Revolutions",
    "tmdb_id": 605,
    "media_type": "movie"
  }
}
```

每个 `label` 以请求的 `language` 返回，找不到时回退到英语。使用 `language=ru` 时，上面的作者显示为 `Чак Паланик`。

## 错误

错误使用 TMDB 的响应体，例如 `{"success": false, "status_code": 7, "status_message": "Invalid API key: You must be granted a valid key."}`。

| HTTP | status_code | 何时出现                             |
| ---- | ----------- | -------------------------------- |
| 400  | 22          | `external_source` 缺失、不是小写或不在列表中。 |
| 401  | 7           | 密钥缺失或错误。                         |
| 402  | 36          | 套餐周期已结束。                         |
| 404  | 34          | `wikidata` 路径中的作品 ID 不存在。        |
| 429  | 25          | 超过每分钟请求数。请等待 `Retry-After` 秒。    |

`find` 上未知的外部 ID 不算错误：预计五个数组都为空。`external_ids` 接口对未知 ID 同样不返回 404，而是返回 200，所有 ID 都是 `null`。见[错误](https://amodb.dev/zh/errors/)和[认证](https://amodb.dev/zh/authentication/)。

## 实用说明

- 第一次解析出外部 ID 时就保存 TMDB ID。之后的调用可以跳过 `find` 直接走详情路径，每部作品省下一个请求。
- 始终检查你想要的数组是否有内容。对同一个 ID，`find` 可能同时返回多个数组。
- 详情和外部 ID 在边缘缓存 6 小时。在这段时间内重复查询会返回已存储的结果。
- `wikidata_id` 可以双向使用：传给 `find` 得到作品，或从 `external_ids` 读取后用于外链。
- 想把 OMDb 风格的 IMDb 查询迁移过来，见 [OMDb 接口](https://amodb.dev/zh/omdb-endpoint/)。解析出作品之后要获取评分，见[评分](https://amodb.dev/zh/ratings/)。

## 常见问题

### find 接口接受哪些外部来源？

external_source 接受十二个值，其中七个能解析：imdb_id、tvdb_id、wikidata_id、kinopoisk_id、facebook_id、twitter_id 和 instagram_id。另外五个返回空数组。该值必填、小写且必须精确，例如 external_source=imdb_id。

### 为什么 find 返回五个数组？

一个 ID 可能指向电影、人物、剧集、单集或季，所以响应为每种类型各设一个数组。在 amodb 中，只有 movie_results、person_results 和 tv_results 有内容。tv_episode_results 和 tv_season_results 始终为空。

### ID 未知时会怎样？

与 TMDB 一样，你会得到状态 200 和五个空数组。读取之前请先确认至少有一个数组有内容。缺少或未知的 external_source 则不同：它返回 400 和 status_code 22。

### 如何获取我已有作品的 Kinopoisk ID？

调用该电影或剧集的 external_ids 接口。它以字符串形式返回 kinopoisk_id，例如《搏击俱乐部》是 361，amodb 不知道时则为 null。把这个字符串连同 external_source=kinopoisk_id 传给 find，即可反向查找。

### 能把 wikidata 追加到详情调用吗？

能。在电影或电视剧详情请求中加上 append_to_response=wikidata，Wikidata 数据块就会出现在 wikidata 键下，在同一个请求中到达，无需额外调用。

## 相关页面

- [电影详情 API](https://amodb.dev/zh/movies/): 路径和 JSON 与 TMDB v3 相同的电影详情 API：按 ID 取电影，用 append_to_response 加入演职员和评分，支持 14 种语言。
- [电视剧 API](https://amodb.dev/zh/tv-series/): 路径和 JSON 与 TMDB v3 相同的电视剧 API。按 ID 获取剧集的季、电视网和下一集，以及内容分级和观看平台。
- [电影与电视剧评分](https://amodb.dev/zh/ratings/): 一次调用返回作品的 IMDb、Kinopoisk、Metacritic、Rotten Tomatoes 和 TMDB 评分，来源未知时为 null。
- [人物详情 API](https://amodb.dev/zh/people/): 路径和 JSON 与 TMDB v3 相同的人物详情 API。按 ID 获取演员或幕后人员，含传记、作品列表、外部 ID 和热门列表。
- [OMDb 兼容接口](https://amodb.dev/zh/omdb-endpoint/): 位于 api.amodb.dev/omdb/ 的 OMDb 兼容接口。用 i 或 t 查找，用 s 搜索，读取 Ratings 数组，只需更换基础 URL。
- [认证](https://amodb.dev/zh/authentication/): 如何发送 amodb 密钥：查询中的 api_key、Bearer 请求头，或 OMDb 的 apikey。含密钥格式、保管和 401 错误。

更新于: 2026-10-18. Source: https://amodb.dev/zh/find-by-external-id/
