> For the complete documentation index, see [llms.txt](https://nvsbl.gitbook.io/apphafen/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://nvsbl.gitbook.io/apphafen/mozilla-add-ons.md).

# Mozilla Add-ons

This app needs three values for a Mozilla AMO connection:

* `API key`
* `API secret`
* `Add-on URLs, slugs, GUIDs, or IDs`

## What each value is

### API key and API secret

These come from your Mozilla Add-ons developer account and are used to sign short-lived JWTs for the AMO API.

Create them here:

1. Sign in to your Mozilla Add-ons developer account.
2. Open the [API credentials management page](https://addons.mozilla.org/en-US/developers/addon/api/key/).
3. Create a new API credential pair if you do not already have one.
4. Copy the displayed `API key`.
5. Copy the displayed `API secret`.

{% hint style="warning" %}
Store the `API secret` when Mozilla shows it. Treat it like a password.
{% endhint %}

{% hint style="info" %}
The AMO account that created the credentials must have access to the add-ons you want to track.

If an add-on is unlisted or not public, the credential owner must be a developer or owner of that add-on.
{% endhint %}

## Add-on URLs, slugs, GUIDs, or IDs

This app does not auto-discover AMO add-ons. You must list the add-ons you want to track explicitly.

This field accepts any of the following:

* Full AMO listing URLs
* Raw AMO slugs
* Raw extension GUIDs
* Numeric AMO add-on IDs
* `Name | URL or ID` entries when you want to provide a fallback label

Examples:

```
https://addons.mozilla.org/en-US/firefox/addon/my-addon/
my-addon
addon@example.com
123456
My Add-on | https://addons.mozilla.org/en-US/firefox/addon/my-addon/
```

You can paste them one per line or comma-separated.

{% hint style="info" %}
The app extracts the identifier from the value you paste and then loads the add-on through the AMO API.

When the add-on response has a usable display name, that name wins.

A `Name | ...` entry is only used as a fallback label.
{% endhint %}

## Required Mozilla-side prerequisites

* The account that owns the `API key` and `API secret` must be able to access the add-ons you are trying to track.
* Listed public add-ons can usually be fetched by known identifier.
* Unlisted or otherwise non-public add-ons require authenticated access tied to a developer or reviewer relationship.
* Your system clock should be correct because Mozilla JWT authentication uses short expiration windows.

## How AMO authentication works

Mozilla’s external API uses a JWT in the `Authorization` header.

The JWT:

* uses the `HS256` signing algorithm
* sets `iss` to your `API key`
* uses a unique `jti`
* includes `iat` and `exp`
* must expire no later than five minutes after `iat`

This app creates that JWT for you automatically from the stored `API key` and `API secret`.

## Quick validation checklist

If the app shows `Mozilla authentication failed.` or cannot import your add-ons, check these in order:

1. Confirm the `API key` and `API secret` were copied from the same AMO credential pair.
2. Confirm there are no leading or trailing spaces in either value.
3. Confirm the AMO account that created the credentials has access to the add-ons you entered.
4. Confirm each add-on entry is a valid AMO URL, slug, GUID, or numeric ID.
5. Confirm your system clock is correct.
6. If the add-on is unlisted or private, confirm the credential owner is actually listed on that add-on as a developer or owner.

## Direct authentication test

You can verify the credentials outside the app by generating a JWT and calling the AMO profile endpoint.

Create a token with this PHP one-liner:

```bash
php -r '
$key = "YOUR_API_KEY";
$secret = "YOUR_API_SECRET";
$iat = time();
$header = rtrim(strtr(base64_encode(json_encode(["alg"=>"HS256","typ"=>"JWT"])), "+/", "-_"), "=");
$payload = rtrim(strtr(base64_encode(json_encode([
  "iss" => $key,
  "jti" => bin2hex(random_bytes(16)),
  "iat" => $iat,
  "exp" => $iat + 300,
])), "+/", "-_"), "=");
$unsigned = $header . "." . $payload;
$signature = rtrim(strtr(base64_encode(hash_hmac("sha256", $unsigned, $secret, true)), "+/", "-_"), "=");
echo $unsigned . "." . $signature;
'
```

Use the resulting token like this:

```bash
curl -H "Authorization: JWT YOUR_JWT_TOKEN" \
  "https://addons.mozilla.org/api/v5/accounts/profile/"
```

Interpretation:

* `200`: credentials are valid
* `401`: wrong key, wrong secret, expired JWT, or system clock issue
* `403`: authenticated, but not allowed to access that endpoint or resource

## Direct add-on test

If authentication works, verify one add-on directly by identifier.

Using a slug:

```bash
curl -H "Authorization: JWT YOUR_JWT_TOKEN" \
  "https://addons.mozilla.org/api/v5/addons/addon/YOUR_ADDON_SLUG/"
```

Using a GUID:

```bash
curl -H "Authorization: JWT YOUR_JWT_TOKEN" \
  "https://addons.mozilla.org/api/v5/addons/addon/YOUR_ADDON_GUID/"
```

If you want to inspect version state too:

```bash
curl -H "Authorization: JWT YOUR_JWT_TOKEN" \
  "https://addons.mozilla.org/api/v5/addons/addon/YOUR_ADDON_IDENTIFIER/versions/?filter=all_with_unlisted&page_size=25"
```

Interpretation:

* `200`: the identifier is correct and the authenticated account can access the add-on
* `401`: authentication problem
* `403`: the account is authenticated but does not have access to that add-on
* `404`: wrong slug, GUID, or ID

## What the app imports from AMO

{% stepper %}
{% step %}

### Loads add-on detail

Loads add-on detail from the AMO add-on detail endpoint.
{% endstep %}

{% step %}

### Resolves the canonical `guid`

Resolves the canonical AMO `guid`.
{% endstep %}

{% step %}

### Imports one Firefox product row

Imports one Firefox product row keyed by that `guid`.
{% endstep %}

{% step %}

### Loads versions

Loads versions to determine:

* current live version
* latest known version
* listed versus unlisted channel
* high-level status mapping
  {% endstep %}
  {% endstepper %}

Because import is explicit, changing the set of tracked AMO add-ons means editing the connection credentials and updating the add-on list.

## Sources

* [Mozilla Add-ons API: Authentication (External)](https://mozilla.github.io/addons-server/topics/api/auth.html)
* [Mozilla Add-ons API: Add-ons](https://mozilla.github.io/addons-server/topics/api/addons)
* [Mozilla Add-ons developer API credentials page](https://addons.mozilla.org/en-US/developers/addon/api/key/)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://nvsbl.gitbook.io/apphafen/mozilla-add-ons.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
