# Price comparison by barcode with Affiliate.com's product search API

Affiliate.com's Product Search API lists each merchant's offer for one product when you filter on its barcode (UPC, EAN or GTIN) and sort by `final_price` ascending. One request costs $0.02: send `POST https://zeroclick.affiliate.com/zcj/jjizyxwem62l/v1/products` with the filter and pay the request's 402 price quote from a wallet.

## At a glance

- **Endpoint:** `POST https://zeroclick.affiliate.com/zcj/jjizyxwem62l/v1/products`, which searches the product catalog
- **Body:** `search` with a `barcode` filter, `sort_by: "final_price"`, `sort_order: "asc"`, `fields` trimmed to the comparison fields, and `per_page`
- **Price:** $0.02 per request
- **Payment:** each request answers with a 402 price quote, paid from a wallet over x402 or MPP, or drawn from prepaid Credits. No account or API key is needed.
- **Response:** `data` (the offers, in price order), `meta` (totals, pages, sort) and `links` (pagination)
- **Limits:** filters in `search` combine with AND, `per_page` defaults to 100, and each page is its own paid request
- **Full purchase flow:** [the buyer skill](https://zeroclick.affiliate.com/zcj/jjizyxwem62l/SKILL.md)

## Compare prices for one barcode

The barcode identifies the same product at every merchant. A filter on it with `=` returns only that product's offers, and sorting by `final_price` in `asc` order puts the lowest price first.

1. Send the search:

   ```bash
   curl -sS -X POST https://zeroclick.affiliate.com/zcj/jjizyxwem62l/v1/products \
     -H 'Content-Type: application/json' \
     -d '{
       "search": [{"field": "barcode", "operator": "=", "value": "4548736132580"}],
       "sort_by": "final_price",
       "sort_order": "asc",
       "fields": ["name", "merchant", "final_price", "regular_price", "on_sale", "currency", "availability", "updated_at"],
       "per_page": 10
     }'
   ```

   The storefront answers with a 402 price quote, with the amount in `payment.amountUsd`.

2. Pay the 402 with an x402 or MPP client and resend the identical request with the payment proof attached. The example request above paid $0.02. The buyer skill has the payment steps.

3. Read the 200 response. The response is a JSON object with `data`, `meta` and `links`. Each item in `data` is one offer with the fields you asked for. The block below shows the response's shape, with each value replaced by its type:

   ```text
   {
     "data": [
       {
         "name": <string>,
         "merchant": {
           "id": <number>, "object_id": <string>, "slug": <string>, "name": <string>,
           "logo_url": <string>, "canonical_id": <string>, "canonical_name": <string>,
           "origin_id": <string>, "links": {"view": <string>, "canonical": <string>}
         },
         "final_price": <number>,
         "regular_price": <number>,
         "on_sale": <boolean>,
         "currency": <string>,
         "availability": <string>,
         "updated_at": <string>
       }
     ],
     "meta": {
       "total": <number>, "from": <number>, "to": <number>,
       "current_page": <number>, "last_page": <number>, "per_page": <number>,
       "fields": [<string>], "after": null,
       "sort_by": <string>, "sort_order": <string>, "trace_id": <string>
     },
     "links": {"self": <string>, "first": <string>, "prev": null, "next": <string>}
   }
   ```

   Offers come in ascending `final_price` order. Compare prices only between offers in the same `currency`. `meta.total` counts all matching offers.

4. Fetch more pages only when `meta.last_page` is above `meta.current_page`. To get the next page, resend the same body with `"page": 2`, then `3`, and so on. Each page costs $0.02. Three pages cost $0.06.

## Read the comparison fields

| Field | What it holds |
| --- | --- |
| `name` | The product name in the merchant's record |
| `merchant` | The merchant: `id`, `name`, `slug`, `canonical_id`, `canonical_name` and `links` |
| `final_price` | The current price after discounts |
| `regular_price` | The original retail price |
| `on_sale` | `true` when the offer is on sale |
| `currency` | The ISO 4217 currency code of both prices |
| `availability` | `InStock`, `OutOfStock`, or null when unknown |
| `updated_at` | The UTC timestamp of the record's last refresh |

If you omit `fields`, the response returns the full record. The full record also carries `direct_url` (the direct product link), `image_url`, `sale_discount`, `stock_quantity` and the rest of the product data.

## Filter to in-stock or on-sale offers

Add filters to the `search` array. They combine with the barcode filter by AND.

| Need | Change to the body |
| --- | --- |
| In-stock offers only | Add `{"field": "availability", "operator": "=", "value": "InStock"}` |
| Offers on sale only | Add `{"field": "on_sale", "operator": "=", "value": true}` |
| Offers at or under a price | Add `{"field": "final_price", "operator": "<=", "value": <your maximum>}` |
| Highest price first | Set `"sort_order": "desc"` |
| Most recently refreshed first | Set `"sort_by": "updated_at"` and `"sort_order": "desc"` |

A changed body is a new request at $0.02. Putting all the filters in the first request avoids a second charge.

## Boundaries

- Product Search returns catalog records. It does not place an order with the merchant.
- Each offer carries `updated_at`, the UTC timestamp of the record's last refresh.
- You pay the price before the request reaches the API, so a request the API rejects with a `422` is charged like any other request.
- Card payment covers pay-as-you-go calls of $0.50 or more.
- To pay smaller charges by card, buy Credits from $0.50 by card, with an agent credential from [auth.md](https://zeroclick.affiliate.com/zcj/jjizyxwem62l/auth.md).

## Errors

| Response | Meaning | Action |
| --- | --- | --- |
| `402` with a `payment` block | The price quote | Pay it and retry the same request, or stop |
| `422` | The API could not process the body | Check field names and values against the API reference, then send a corrected request. The new request is charged again. |
| `rate_limit_exceeded` | The rate limit was reached | Wait `retry_after` or `Retry-After`, then retry |
| `settlement_failed` | The signed payment did not settle. `settlementReason` says why. | Fix the wallet and resend the request for a fresh 402 |
| `usage_exhausted` | Prepaid Credits ran out | Top up with `POST https://zeroclick.affiliate.com/zcj/jjizyxwem62l/extend` and your bearer, or pay per request |

## Frequently asked questions

### How do I find the lowest price for a product across retailers with an API?

Send one Product Search request with the product's barcode as a `search` filter, with `sort_by` set to `final_price` and `sort_order` set to `asc`. The first offer in `data` has the lowest `final_price` among the matches, provided the offers share a `currency`. The request costs $0.02.

### What if I have an ASIN, a SKU or a product page URL instead of a barcode?

Tool Convert turns it into a barcode at $0.02 per request. Use `POST https://zeroclick.affiliate.com/zcj/jjizyxwem62l/v1/tools/convert/asin-to-barcode` (with `config.asin.locale`), `/v1/tools/convert/sku-to-barcode` (with `config.merchant`) or `/v1/tools/convert/url-to-barcode`. Then send the search with `<barcode from the conversion>` as the filter value. One conversion plus one search costs $0.04.

### How current are the prices in the results?

Each offer carries `updated_at`, the UTC timestamp of the record's last refresh. Read it alongside `final_price` to see how recent each price is.

### Do I need an API key for this price comparison API?

No. You pay pay-as-you-go requests per call through the 402 price quote, with no account or key. Only a Credits purchase needs a bearer credential from the storefront.

## Keep reading

- [Buyer skill](https://zeroclick.affiliate.com/zcj/jjizyxwem62l/SKILL.md): the full purchase flow
- [How to pay](https://zeroclick.affiliate.com/zcj/jjizyxwem62l/payment.md): rails, Credits and top-ups
- [Product Search service](https://zeroclick.affiliate.com/zcj/jjizyxwem62l/services/product-search): its prices and plans
- [API reference](https://zeroclick.affiliate.com/zcj/jjizyxwem62l/openapi.json): every request field and response schema
- [Error reference](https://zeroclick.affiliate.com/zcj/jjizyxwem62l/errors.md): every error code and what to do

---

Updated 2026-10-16. All Affiliate.com guides: https://zeroclick.affiliate.com/guides.md. Storefront: https://zeroclick.affiliate.com/zcj/jjizyxwem62l/llms.txt.
