# Search products across merchants with Affiliate.com's API

Affiliate.com's Product Search API searches products across all Affiliate.com merchants in one request. It returns product records with each merchant's price and availability. Each request costs $0.02: send `POST https://zeroclick.affiliate.com/zcj/xa70g4d88447/v1/products` with a `search` value and `per_page`, pay the 402 price quote over x402 or MPP, and retry the same request.

## At a glance

- **Endpoint:** `POST https://zeroclick.affiliate.com/zcj/xa70g4d88447/v1/products`, one search per request
- **Body:** `search` (required, a text string or an array of filters) and `per_page` (default 100). Optional fields are `page`, `after`, `fields`, `sort_by`, `sort_order` and `facets`.
- **Price:** $0.02 per request, whatever `per_page` asks for.
- **Payment:** a 402 is the price quote. You pay it and retry. x402 (Base USDC) and MPP (Tempo USDC) are the wallet rails. You need no account or API key.
- **Response:** `data` (product records), `meta` (totals, page counters, `after` cursor), `links` (`next` page)
- **Limits:** `page` covers the first 10,000 results and the `after` cursor goes beyond that. A request takes up to 20 `facets`.
- **Full purchase flow:** [the buyer skill](https://zeroclick.affiliate.com/zcj/xa70g4d88447/SKILL.md)

## Search the catalog and pay per request

1. Send the search. Set `search` and `per_page`:

   ```bash
   curl -sS -X POST https://zeroclick.affiliate.com/zcj/xa70g4d88447/v1/products \
     -H 'Content-Type: application/json' \
     -d '{"search": "Sony WH-1000XM5", "per_page": 3}'
   ```

   The storefront answers with a 402 quoting $0.02. The body carries `payment.amountUsd`, the `plan` and a `protocols` block with one challenge per rail. The same challenges arrive in the `payment-required` header (x402) and the `www-authenticate` header (MPP). Nothing is charged at this point, so you can safely stop here.

2. Pay the challenge and resend the identical request with the proof attached. On x402 the signed payload goes in `x-payment`. On MPP it goes in `Authorization: Payment <credential>`:

   ```bash
   curl -sS -X POST https://zeroclick.affiliate.com/zcj/xa70g4d88447/v1/products \
     -H 'Content-Type: application/json' \
     -H 'x-payment: <signed x402 payload>' \
     -d '{"search": "Sony WH-1000XM5", "per_page": 3}'
   ```

   A standard x402 or MPP client reads the challenge from the headers, pays it and retries for you. The search above paid $0.02 and returned three product records in `data`, with `meta` and `links` alongside.

3. Read the records. Each item in `data` describes one product at one merchant:

   | Field | Holds |
   | --- | --- |
   | `id`, `name`, `description`, `category` | The product |
   | `image_url` | The primary image |
   | `currency`, `regular_price`, `final_price` | The price before and after discounts |
   | `on_sale`, `sale_discount` | Whether the offer is discounted |
   | `availability`, `stock_quantity` | `InStock`, `OutOfStock` or null when unknown |
   | `merchant` | The merchant's `id`, `name`, `slug` and `logo_url` |
   | `identifiers` | Keys for `barcode`, `ean`, `gtin`, `upc`, `isbn`, `mpn`, `sku` and `asin` |
   | `added_at`, `updated_at` | When the record was added and last refreshed |

   `meta.total` is the number of matching products. Send `fields` as an array of field names to return only those fields.

4. Page through the results. Resend the same body with the next `page`:

   ```json
   {"search": "Sony WH-1000XM5", "per_page": 3, "page": 2}
   ```

   Each page is a new request with its own 402. Stop when `meta.current_page` equals `meta.last_page`. Beyond 10,000 results, send `after` with the `meta.after` value from the previous response instead of `page`.

## Choose the search criteria

A plain string matches broadly across product fields. An array of filter objects matches precisely, and the filters combine with AND.

| You want | `search` value |
| --- | --- |
| A broad match on a phrase | `"Sony WH-1000XM5"` |
| Names containing a phrase | `[{"field": "name", "operator": "LIKE", "value": "noise cancelling"}]` |
| A price ceiling | `[{"field": "final_price", "operator": "<=", "value": 300}]` |
| One merchant | `[{"field": "merchant.name", "operator": "=", "value": "<merchant name>"}]` |
| In-stock offers only | `[{"field": "availability", "operator": "=", "value": "InStock"}]` |

The common filter fields are `any`, `name`, `brand`, `category`, `barcode`, `final_price`, `on_sale`, `availability`, `merchant.id` and `merchant.name`. Text fields take `=`, `!=`, `LIKE` and `NOT LIKE`. Numeric fields take `=`, `!=`, `>`, `<`, `>=` and `<=`. To list the cheapest offers first, set `"sort_by": "final_price"` and `"sort_order": "asc"`.

## Boundaries

- One search per request, with no batch parameter. Ten pages cost $0.20.
- An unpaid 402 charges nothing. A payment covers only the request it was quoted for.
- Card payment per call applies only to calls of $0.50 or more. A single search therefore pays over a wallet rail, or draws from prepaid Credits.
- Prepaid Credits cost at least $0.50 per purchase. [The buyer skill](https://zeroclick.affiliate.com/zcj/xa70g4d88447/SKILL.md) covers buying them.

## Errors

| Response | Meaning | Action |
| --- | --- | --- |
| `402` with a `payment` block and no `reason` | The per-request price quote | Pay it and retry the identical request, or stop |
| `400 invalid_request` | The body is malformed | Fix the JSON and resend |
| `settlement_failed` | The payment did not settle. `settlementReason` says why. | Fix the wallet, then send a fresh request for a new 402 |
| `409 payment_request_mismatch` | A payment was reused for a different request, such as another page | Request a fresh 402 for each body |
| `payment_consumed` | The payment was already settled | Check whether the earlier search was delivered before paying again |
| `429` | Too Many Requests | Wait, then retry with bounded backoff |

## Frequently asked questions

### Does the Affiliate.com product search API need an account or an API key?

No. Pay-as-you-go searches need no account, no registration and no key. The signed payment for each request's 402 is the only credential the call needs.

### How much does a product search cost?

Each request costs $0.02. A search that reads five pages costs $0.10, and the 402 states the exact amount before each payment.

### Can one request search every merchant at once?

Yes. Product Search covers all Affiliate.com merchants in one request. To narrow the results to one merchant, add a filter on `merchant.name` or `merchant.id`.

### Can I pay for product searches by card?

Not per search, since card payment per call starts at $0.50. Card can fund prepaid Credits instead, and [the buyer skill](https://zeroclick.affiliate.com/zcj/xa70g4d88447/SKILL.md) has the steps.

### How do I get only the fields I need?

Send `fields` as an array of product field names, for example `["name", "final_price", "merchant"]`. When `fields` is omitted, the response returns every field.

## Keep reading

- [Buyer skill](https://zeroclick.affiliate.com/zcj/xa70g4d88447/SKILL.md): the full purchase flow
- [API reference](https://zeroclick.affiliate.com/zcj/xa70g4d88447/openapi.json): every request field and response schema
- [How to pay](https://zeroclick.affiliate.com/zcj/xa70g4d88447/payment.md): the 402, x402, MPP, card and Credits
- [Error reference](https://zeroclick.affiliate.com/zcj/xa70g4d88447/errors.md): every error code and the action for each

---

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