試してみた
- Amazon Product Advertising API(PA-API)がCreators APIとして置き換わった
- amazonアソシエイトに登録し、3件の注文を獲得して承認を受ける
- 30日で10件以上の発送済みがある場合のみAPIが200を返す
仕様まとめ
Amazon Creators API 最低限の疎通確認とハマりどころ
前提:使えるようになるまで
必要なもの
- Amazon アソシエイト承認済みアカウント(日本:affiliate.amazon.co.jp)
- 過去30日で 10 件以上の適格販売(発送済み) ← Creators API の利用資格条件
- https://affiliate.amazon.co.jp/creatorsapi で発行する Credential ID / Secret
- Partner Tag
注意点
- アソシエイトアカウントが承認済みでも、Creators API の利用には 別途 過去30日10件のハードルがある
- Amazonデバイス / Amazon Music / Prime Video / ギフトカードは「適格販売」にカウントされない
- 売上が落ちて30日 0件状態になると 一時停止。発送が再開されると 約2日で自動復元
最低限の動作確認コード
.env を用意:
CREATORS_CLIENT_ID=amzn1.application-oa2-client.xxxxxxxx
CREATORS_CLIENT_SECRET=amzn1.oa2-cs.v1.xxxxxxxx
CREATORS_PARTNER_TAG=xxxxxx-22
CREATORS_MARKETPLACE=www.amazon.co.jp
疎通テストスクリプト:
import json, os, requests
from dotenv import load_dotenv
load_dotenv()
TOKEN_URL = "https://api.amazon.co.jp/auth/o2/token"
GET_ITEMS_URL = "https://creatorsapi.amazon/catalog/v1/getItems"
r = requests.post(TOKEN_URL,
headers={"Content-Type": "application/json"},
json={
"grant_type": "client_credentials",
"client_id": os.environ["CREATORS_CLIENT_ID"],
"client_secret": os.environ["CREATORS_CLIENT_SECRET"],
"scope": "creatorsapi::default",
}, timeout=30)
r.raise_for_status()
token = r.json()["access_token"]
print(f"token ok: {token[:24]}...")
r = requests.post(GET_ITEMS_URL,
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"x-marketplace": "www.amazon.co.jp",
},
json={
"partnerTag": os.environ["CREATORS_PARTNER_TAG"],
"itemIds": ["B0GGY53D74"],
"resources": [
"images.primary.large",
"itemInfo.title",
"itemInfo.byLineInfo",
"offersV2.listings.price",
],
}, timeout=30)
print(r.status_code)
print(json.dumps(r.json(), ensure_ascii=False, indent=2))
成功時のレスポンス(getItems)
{
"itemsResult": {
"items": [{
"asin": "B0GGY53D74",
"detailPageURL": "https://www.amazon.co.jp/dp/B0GGY53D74?tag=...",
"images": {"primary": {"large": {"url": "...", "width": 396, "height": 500}}},
"itemInfo": {
"title": {"displayValue": "Animage (アニメージュ) 2026年 05月号 [雑誌]"},
"byLineInfo": {
"brand": {"displayValue": "徳間書店"},
"contributors": [{"name": "Animage編集部", "roleType": "author"}]
}
},
"offersV2": {"listings": [{"price": {"money": {"amount": 856, "currency": "JPY"}}}]}
}]
}
}
これが返ってくれば疎通 OK。
使えないときの典型エラー
1. AssociateNotEligible(HTTP 403)
{
"message": "Your account does not currently meet the eligibility requirements.",
"reason": "AssociateNotEligible",
"type": "AccessDeniedException"
}
原因: 過去30日で適格販売が10件未満。
対処:
- アソシエイトのレポートで「過去30日・確定済み・発送済み」件数を確認
- 適格でない商品(Amazonデバイス、Prime Video、ギフトカード等)が混じってないか確認
- partner_tag が複数ある場合、別タグに売上が立っていないか確認
- 復元には 発送完了から約2日のラグ あり
補足:トークン取得(/auth/o2/token)は資格に関係なく通る。AssociateNotEligible が出るのは getItems / searchItems 側。
2. ValidationException — resources のフィールド名間違い(HTTP 400)
{
"message": "...failed to satisfy constraint: Member must satisfy enum value set: [searchRefinements, itemInfo.externalIds, ...]",
"reason": "FieldValidationFailed",
"type": "ValidationException"
}
よくある誤り:
- offersV2.listings.programEligibility ← 存在しない(KU 判定のために試したくなるが NG)
- 任意の typo
searchItems で使える resources(実機検証で判明):
searchRefinements
parentASIN
itemInfo.title
itemInfo.byLineInfo
itemInfo.externalIds
itemInfo.classifications
itemInfo.manufactureInfo
itemInfo.productInfo
itemInfo.contentInfo
itemInfo.contentRating
itemInfo.features
itemInfo.technicalInfo
itemInfo.tradeInInfo
images.primary.small / medium / large / highRes
images.variants.small / medium / large / highRes
browseNodeInfo.browseNodes
browseNodeInfo.browseNodes.ancestor
browseNodeInfo.browseNodes.salesRank
browseNodeInfo.websiteSalesRank
offersV2.listings.price
offersV2.listings.condition
offersV2.listings.availability
offersV2.listings.dealDetails
offersV2.listings.isBuyBoxWinner
offersV2.listings.loyaltyPoints
offersV2.listings.merchantInfo
offersV2.listings.type
customerReviews.starRating
customerReviews.count
3. ValidationException — SearchIndex の値が無効(HTTP 400)
{
"fieldList": [{
"name": "InvalidParameterValue",
"message": "The value Magazines provided in the request for SearchIndex is invalid."
}],
"type": "ValidationException"
}
原因: 日本のロケール(amazon.co.jp)では SearchIndex=Magazines は存在しない。
対処: 雑誌の検索でも SearchIndex=KindleStore(Kindle 版なら)or Books を使う。BrowseNodeId でカテゴリ絞り込みする。
4. ThrottleException(HTTP 429)
{
"message": "Request rate limit exceeded.",
"type": "ThrottleException"
}
原因: レート制限。Creators API は概ね 1 TPS 程度。
対処:
- 呼び出し間に 1.0〜1.5 秒のウェイトを入れる
- 429 を受けたら 3 秒スリープしてリトライ
- 大量バッチは getItems(10 ASIN/req)を使ってリクエスト数を圧縮
実装例:
import time, threading
class CreatorsClient:
def __init__(self, min_interval_sec=1.2):
self._lock = threading.Lock()
self._last_call_at = 0.0
self._min_interval = min_interval_sec
def _throttle(self):
with self._lock:
elapsed = time.time() - self._last_call_at
if elapsed < self._min_interval:
time.sleep(self._min_interval - elapsed)
self._last_call_at = time.time()
5. トークン取得自体が失敗する
| ステータス |
原因 |
invalid_client |
CLIENT_ID / SECRET の typo、改行混入 |
invalid_scope |
scope を creatorsapi::default 以外にしている |
unsupported_grant_type |
grant_type が client_credentials 以外 |
Content-Type は application/json で JSON ボディを送ること(application/x-www-form-urlencoded のサンプルもあるが、api.amazon.co.jp の v3.3 は JSON で動作確認済)。
チートシート
| 項目 |
値 |
| トークン URL |
https://api.amazon.co.jp/auth/o2/token |
| getItems URL |
https://creatorsapi.amazon/catalog/v1/getItems |
| searchItems URL |
https://creatorsapi.amazon/catalog/v1/searchItems |
| scope |
creatorsapi::default |
| token TTL |
3600 秒(1 時間) |
| marketplace ヘッダ |
x-marketplace: www.amazon.co.jp |
| getItems 上限 |
1 リクエスト 10 ASIN |
| searchItems 上限 |
1 ページ 10 件、itemPage 1〜10 で最大 100 件 |
| レート制限 |
約 1 TPS |
| 利用資格 |
過去30日に 10 件以上の適格販売(発送済み) |
Kindle Unlimited 判定の Tips
- レスポンスに「KU 対象フラグ」は 存在しない
- 代わりに
browseNodeInfo.browseNodes の祖先を再帰的に辿り、id=3197885051(Kindle Unlimited:読み放題 ジャンル)が含まれるかでチェック
def is_kindle_unlimited(item):
KU_NODE_ID = "3197885051"
def has_ancestor(node, target):
if node.get("id") == target:
return True
a = node.get("ancestor")
return has_ancestor(a, target) if a else False
for n in item.get("browseNodeInfo", {}).get("browseNodes", []):
if has_ancestor(n, KU_NODE_ID):
return True
return False
resources に browseNodeInfo.browseNodes.ancestor を必ず含めること。