Amazon Creators API - Elixir Client
An Elixir client library for the Amazon Creators API with automatic token caching and management.
Features
- ✅ Support for all Amazon regions (NA, EU, FE)
- ✅ Automatic OAuth token management with caching
- ✅ Token auto-refresh before expiration
- ✅ GenServer-based token cache for performance
- ✅ Comprehensive error handling
- ✅ Full test coverage
- ✅ Easy-to-use API
Installation
Add amazon_creators_api to your list of dependencies in mix.exs:
def deps do
[
{:amazon_creators_api, "~> 0.4.0"}
]
end
Configuration
Set up your Amazon Creators API credentials as environment variables:
export CREATORS_API_CLIENT_ID="your_client_id"
export CREATORS_API_CLIENT_SECRET="your_client_secret"
export CREATORS_API_PARTNER_TAG="yourpartner-20"
export CREATORS_API_VERSION="3.2"
Associates Central hands you a credential id, a secret and a version when
you create a credential. Pass that version as the version option — it selects
which authentication flow is used:
| Version | Credentials | Auth endpoint | Scope | Catalog auth header |
|---|---|---|---|---|
3.1 NA, 3.2 EU, 3.3 FE | amzn1.application-oa2-client.… / amzn1.oa2-cs.v1.… | https://api.amazon.com/auth/o2/token, JSON body | creatorsapi::default | Bearer <token> |
2.1 NA, 2.2 EU, 2.3 FE | Cognito app client | regional Cognito endpoint, form encoded | creatorsapi/default | Bearer <token>, Version <version> |
Credentials created from v3.0 onwards use Login with Amazon. Older 2.x credentials keep working, and omitting the option falls back to the 2.x version for the region, so existing integrations are unaffected.
Pass the version that matches your credential: a 3.x credential sent through the
2.x flow fails with {:auth_failed, 400, "{\"error\":\"invalid_client\"}"}.
Usage
Simple Usage (Recommended)
The easiest way to use the API is with fetch_items/2, which handles token management automatically:
# Fetch a single item
opts = [
region: :na, # or :eu, :fe
marketplace: "www.amazon.com",
partner_tag: System.get_env("CREATORS_API_PARTNER_TAG"),
client_id: System.get_env("CREATORS_API_CLIENT_ID"),
client_secret: System.get_env("CREATORS_API_CLIENT_SECRET"),
version: System.get_env("CREATORS_API_VERSION")
]
case AmazonCreatorsAPI.fetch_items("B09B2SBHQK", opts) do
{:ok, %{"itemsResult" => %{"items" => items}}} ->
Enum.each(items, fn item ->
IO.puts(item["itemInfo"]["title"]["displayValue"])
IO.puts(item["detailPageURL"])
end)
{:error, reason} ->
IO.puts("Error: #{inspect(reason)}")
end
Fetch Multiple Items
asins = ["B09B2SBHQK", "B09B8V1LZ3", "B0BZTW3TCH"]
{:ok, %{"itemsResult" => %{"items" => items}}} =
AmazonCreatorsAPI.fetch_items(asins, opts)
IO.puts("Fetched #{length(items)} items")
European Marketplaces
opts = [
region: :eu,
marketplace: "www.amazon.de",
partner_tag: "yourpartner-21",
client_id: System.get_env("CREATORS_API_CLIENT_ID"),
client_secret: System.get_env("CREATORS_API_CLIENT_SECRET")
]
AmazonCreatorsAPI.fetch_items("B09B2SBHQK", opts)
Custom Resources
By default, the API fetches common product information. You can specify custom resources:
opts = [
region: :na,
marketplace: "www.amazon.com",
partner_tag: "yourpartner-20",
client_id: System.get_env("CREATORS_API_CLIENT_ID"),
client_secret: System.get_env("CREATORS_API_CLIENT_SECRET"),
resources: [
"itemInfo.title",
"itemInfo.features",
"offersV2.listings.price",
"images.primary.large"
]
]
AmazonCreatorsAPI.fetch_items("B09B2SBHQK", opts)
Available Resources
Item Information:
itemInfo.titleitemInfo.featuresitemInfo.byLineInfoitemInfo.contentInfoitemInfo.contentRatingitemInfo.classificationsitemInfo.externalIdsitemInfo.manufactureInfoitemInfo.productInfoitemInfo.technicalInfoitemInfo.tradeInInfo
Images:
images.primary.smallimages.primary.mediumimages.primary.largeimages.primary.highResimages.variants.smallimages.variants.mediumimages.variants.largeimages.variants.highRes
Offers (Version 2):
offersV2.listings.priceoffersV2.listings.availabilityoffersV2.listings.conditionoffersV2.listings.dealDetailsoffersV2.listings.isBuyBoxWinneroffersV2.listings.loyaltyPointsoffersV2.listings.merchantInfooffersV2.listings.type
Browse Nodes:
browseNodeInfo.browseNodesbrowseNodeInfo.browseNodes.ancestorbrowseNodeInfo.browseNodes.salesRankbrowseNodeInfo.websiteSalesRank
Customer Reviews:
customerReviews.countcustomerReviews.starRating
Other:
parentASIN
Manual Token Management
For advanced use cases where you want to manage tokens yourself:
# Get a token (cached automatically)
{:ok, token_data} = AmazonCreatorsAPI.get_token(:na, client_id, client_secret, "3.0")
# Use the token for multiple requests
{:ok, items1} = AmazonCreatorsAPI.get_items(
"B09B2SBHQK",
"www.amazon.com",
"yourpartner-20",
token_data["access_token"],
token_data["version"]
)
{:ok, items2} = AmazonCreatorsAPI.get_items(
"B09B8V1LZ3",
"www.amazon.com",
"yourpartner-20",
token_data["access_token"],
token_data["version"]
)
Monitoring Token Cache
# Get cache statistics
stats = AmazonCreatorsAPI.token_stats()
# => %{"na:your_client_id:3.0" => %{ttl_seconds: 3540, expires_at: 1735123456}}
# Clear cache (useful for testing or forcing refresh)
AmazonCreatorsAPI.clear_token_cache()
Regions and Marketplaces
North America (NA) - Version 2.1
- United States:
www.amazon.com - Canada:
www.amazon.ca - Mexico:
www.amazon.com.mx - Brazil:
www.amazon.com.br
Europe (EU) - Version 2.2
- United Kingdom:
www.amazon.co.uk - Germany:
www.amazon.de - France:
www.amazon.fr - Italy:
www.amazon.it - Spain:
www.amazon.es - Netherlands:
www.amazon.nl - Belgium:
www.amazon.com.be - Egypt:
www.amazon.eg - India:
www.amazon.in - Ireland:
www.amazon.ie - Poland:
www.amazon.pl - Saudi Arabia:
www.amazon.sa - Sweden:
www.amazon.se - Turkey:
www.amazon.com.tr - UAE:
www.amazon.ae
Far East (FE) - Version 2.3
- Japan:
www.amazon.co.jp - Singapore:
www.amazon.sg - Australia:
www.amazon.com.au
Error Handling
The API returns standard Elixir {:ok, result} or {:error, reason} tuples:
case AmazonCreatorsAPI.fetch_items("INVALID_ASIN", opts) do
{:ok, items} ->
IO.inspect(items)
{:error, :not_found} ->
IO.puts("Item not found")
{:error, :unauthorized} ->
IO.puts("Invalid credentials")
{:error, {:auth_failed, status, body}} ->
IO.puts("Authentication failed: #{status}")
{:error, {:http_error, status, body}} ->
IO.puts("HTTP error: #{status}")
{:error, {:request_failed, reason}} ->
IO.puts("Request failed: #{inspect(reason)}")
end
Token Caching
The library automatically caches authentication tokens using a GenServer. Tokens are:
- Cached per region and client ID combination
- Automatically refreshed 60 seconds before expiration
- Reused across multiple API calls for better performance
- Thread-safe for concurrent applications
Testing
Run the test suite:
mix test
Run tests with coverage:
mix coveralls
Run tests with detailed coverage:
mix coveralls.detail
Testing with Mocks
The library includes a built-in mocking framework that makes it easy to test your application code without making real API calls.
Configuration
Configure your test environment to use the mock HTTP client:
# config/test.exs
import Config
config :amazon_creators_api,
http_client: AmazonCreatorsAPI.HTTPClientMock
Basic Usage
In your tests, set up expectations for HTTP requests:
defmodule MyAppTest do
use ExUnit.Case
setup do
AmazonCreatorsAPI.HTTPClientMock.reset()
:ok
end
test "fetches product information" do
# Set up mock response
AmazonCreatorsAPI.HTTPClientMock.expect_post(
{:ok, %{status_code: 200, body: ~s({"access_token": "test_token", "expires_in": 3600})}}
)
AmazonCreatorsAPI.HTTPClientMock.expect_post(
{:ok, %{status_code: 200, body: ~s({"itemsResult": {"items": [{"asin": "B09B2SBHQK"}]}})}}
)
# Call your function that uses the API
{:ok, result} = AmazonCreatorsAPI.fetch_items("B09B2SBHQK",
region: :na,
marketplace: "www.amazon.com",
partner_tag: "test-20",
client_id: "test_id",
client_secret: "test_secret"
)
# Verify the result
assert result["itemsResult"]["items"] == [%{"asin" => "B09B2SBHQK"}]
# Optionally verify the requests made
requests = AmazonCreatorsAPI.HTTPClientMock.get_requests()
assert length(requests) == 2
end
end
Multiple Sequential Calls
Queue multiple responses for sequential API calls:
# First call returns success
AmazonCreatorsAPI.HTTPClientMock.expect_post(
{:ok, %{status_code: 200, body: ~s({"access_token": "token1"})}}
)
# Second call returns success
AmazonCreatorsAPI.HTTPClientMock.expect_post(
{:ok, %{status_code: 200, body: ~s({"access_token": "token2"})}}
)
Error Responses
Test error handling by mocking error responses:
AmazonCreatorsAPI.HTTPClientMock.expect_post(
{:error, %{reason: :timeout}}
)
# Or mock HTTP errors
AmazonCreatorsAPI.HTTPClientMock.expect_post(
{:ok, %{status_code: 401, body: ~s({"error": "unauthorized"})}}
)
Custom HTTP Client
You can also implement your own HTTP client for testing or production use:
defmodule MyApp.CustomHTTPClient do
@behaviour AmazonCreatorsAPI.HTTPClient
@impl true
def post(url, body, headers) do
# Your custom implementation
{:ok, %{status_code: 200, body: "{}"}}
end
end
# config/config.exs
config :amazon_creators_api,
http_client: MyApp.CustomHTTPClient
Architecture
The library consists of two main modules:
- AmazonCreatorsAPI: Main API module with public functions
- AmazonCreatorsAPI.TokenManager: GenServer that manages token caching
The TokenManager is automatically started as part of your application's supervision tree.
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues related to the Amazon Creators API itself, please refer to the official Amazon documentation.
For issues with this library, please open an issue on Codeberg.