Amazon Creators API - Elixir Client

An Elixir client library for the Amazon Creators API with automatic token caching and management.

Features

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:

VersionCredentialsAuth endpointScopeCatalog auth header
3.1 NA, 3.2 EU, 3.3 FEamzn1.application-oa2-client.… / amzn1.oa2-cs.v1.…https://api.amazon.com/auth/o2/token, JSON bodycreatorsapi::defaultBearer <token>
2.1 NA, 2.2 EU, 2.3 FECognito app clientregional Cognito endpoint, form encodedcreatorsapi/defaultBearer <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

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:

Images:

Offers (Version 2):

Browse Nodes:

Customer Reviews:

Other:

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

Europe (EU) - Version 2.2

Far East (FE) - Version 2.3

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:

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:

  1. AmazonCreatorsAPI: Main API module with public functions
  2. 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.