# Barcode Price Checker: UPC & EAN Price Compare (`cleanpull/barcode-price-checker`) Actor

Look up prices for any UPC, EAN or GTIN barcode across Amazon, Best Buy and Target, matched exactly, plus Walmart, eBay and any store on Google Shopping. Price comparison, MAP checks, your price position and change monitoring, with results in seconds.

- **URL**: https://apify.com/cleanpull/barcode-price-checker.md
- **Developed by:** [CleanPull](https://apify.com/cleanpull) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 product with offers

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Barcode Price Checker: UPC & EAN Price Compare

Paste **barcodes** (UPC, EAN, GTIN) and see **every store's price**, **who is selling below your MAP**, and **where your own price ranks**, in seconds. **Amazon** and **Best Buy** are searched **by the barcode itself**; **Walmart, Target, eBay and any store you name** come from Google Shopping, matched by **model number**, with each marketplace seller by name. Schedule it and get **only what changed**: a new seller, a price drop, a new lowest price, a seller going below MAP.

From our test runs on one barcode (UPC 027242923232, Sony WH-1000XM5): **21 offers from 16 stores** in one record, lowest price and store at the top; with a $329.99 MAP, **15 sellers below it**, each with its price, how far below, and a link.

### What you get for each barcode

- **Every offer, cheapest first**: store, marketplace seller, price, was-price, condition, stock where the store states it, link, and the store's own id (Best Buy SKU, ASIN).
- **The lowest price and where**, the highest, and the spread between them.
- **MAP violations**: each seller below your minimum advertised price, by how much, with a link to the listing.
- **Your price position**: how many offers undercut your price.
- **How each price was matched**: `barcode`, `model` or `name`, with a confidence score, so you can trust a price at a glance.
- **Changes only, on a schedule**: new and removed sellers, price drops and rises, stock changes, new lowest prices, tracked seller by seller.

### Built for

- **Brands and distributors enforcing MAP**: a daily list of who is below MAP, with links to send to the seller or marketplace.
- **Resellers and repricers**: the market price of every SKU you carry, and alerts when a competitor moves.
- **Buyers, deal sites and procurement**: the cheapest store for a product list, from barcodes you already have.

### How it finds prices

- **Exact by barcode.** Amazon and Best Buy are searched with the barcode, so their price belongs to the barcode's product: the same item, colour and edition.
- **Any store on Google Shopping.** Walmart and Target by default; add eBay, Home Depot, Lowe's, Newegg, Crutchfield, B\&H Photo, or any store as named on Google Shopping. Marketplace sellers come with their names (`Walmart` · `Secondipity`).
- **Matched by model number.** A Google listing is kept when its title carries the product's model number (WH-1000XM5, AF101), taken from the stores' own product data. Another colour (`/S` for `/B`), a bundle or add-on, a store outside the US, or a price far from the barcode-matched prices is set aside with the reason, never mixed into the lowest price or MAP.
- **Target and Best Buy through our data service (optional).** With `serviceStores`, Target and Best Buy are looked up by the barcode through a third-party web data service that CleanPull holds the account for (nothing to set up, no key in your input). A store's offer is kept only when the store's own record states the same barcode. Every barcode of the run goes in one search per store, which takes **3 to 5 minutes per run** whatever the number of barcodes, so it suits scheduled runs and lists more than one-off lookups.
- **Honest about every source.** Each product says per store whether it was found, not found or failed, so an empty answer is never a silent failure.
- **Results in seconds.** Products are checked in parallel and every record is complete when the run ends.

### Input

| Field                                  | Type                 | What it does                                                                                                                                              |
| -------------------------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `products`                             | array                | UPC (12), EAN (13), GTIN-14 or EAN-8, or a product name (Google Shopping only)                                                                            |
| `sources`                              | array                | `amazon`, `bestbuy`, `google` (default); `target` by barcode is optional (see Limits)                                                                     |
| `serviceStores`                        | array                | Optional, off by default: `target`, `bestbuy` looked up by barcode through CleanPull's marketplace data service. Slow: 3 to 5 minutes per run (see below) |
| `googleStores`                         | array                | Stores to search on Google Shopping, one request each (default Walmart, Target)                                                                           |
| `googleNameSearch`                     | boolean              | Also one unfiltered Google Shopping search (other stores, marketplace sellers); default on                                                                |
| `conditions`                           | array                | `new` (default), `renewed`, `used`, `open-box` (`refurbished` from saved inputs means `renewed`); offers of unknown condition are kept                    |
| `minConfidence`, `includeSetAside`     | number, boolean      | Match threshold (default 0.7); also return set-aside listings with the reason                                                                             |
| `mapPrices`, `myPrices`                | objects              | `{"barcode": price}`: MAP violations; how many offers are cheaper than you                                                                                |
| `monitorMode`, `monitorName`           | boolean, string      | Changes only, per named watch                                                                                                                             |
| `changeTypes`, `minPriceChangePercent` | array, number        | `new-offer`, `offer-removed`, `price-down`, `price-up`, `stock`, `new-lowest`; minimum move                                                               |
| `maxRunCostUsd`                        | number               | Optional. Max cost per run: no product starts once it could pass this. For scheduled runs, which may have no spending limit of their own                  |
| `outputFormat`                         | `products`, `offers` | One record per product, or one row per offer                                                                                                              |
| `maxConcurrency`, `fields`             | integer, array       | Products at once (default 5); return only these fields                                                                                                    |

`barcodes`, `gtins`, `eans` and `upcs` are accepted as names for the product list too.

#### Example inputs

Prices for three products, with eBay as well:

```json
{
  "products": ["027242923232", "045496590475", "017817846141"],
  "googleStores": ["Walmart", "Target", "eBay"]
}
```

MAP check, daily, reporting only changes:

```json
{
  "products": ["027242923232"],
  "mapPrices": { "027242923232": 329.99 },
  "monitorMode": true,
  "monitorName": "sony-map",
  "changeTypes": ["new-offer", "price-down", "new-lowest"]
}
```

Exact barcode prices only (Amazon and Best Buy), the cheapest way:

```json
{ "products": ["027242923232"], "sources": ["amazon", "bestbuy"] }
```

### Output

A product record (real, shortened to three of its 21 offers):

```json
{
  "recordType": "product",
  "barcode": "027242923232",
  "title": "Sony - WH-1000XM5 Wireless Noise Cancelling Over-the-Ear Headphones - Black",
  "brand": "Sony",
  "model": "WH1000XM5/B",
  "lowestPrice": 183.99,
  "lowestPriceStore": "Amazon",
  "lowestPriceCondition": "unknown",
  "lowestNewPrice": 198,
  "lowestNewPriceStore": "Best Buy",
  "conditionCounts": { "new": 20, "renewed": 0, "used": 0, "open-box": 0, "unknown": 1 },
  "highestPrice": 399.99,
  "priceSpreadPercent": 117.4,
  "storeCount": 16,
  "offerCount": 21,
  "sources": { "amazon": "found", "bestbuy": "found", "google": "found" },
  "mapViolations": [],
  "mapUnconfirmed": [],
  "mapOtherCondition": [],
  "offers": [
    {
      "source": "amazon",
      "store": "Amazon",
      "price": 183.99,
      "condition": "unknown",
      "conditionBasis": "none",
      "offerType": "lowest-offer",
      "offerCount": 19,
      "url": "https://www.amazon.com/dp/B0CFSD4TSQ",
      "matchType": "barcode",
      "confidence": 1
    },
    {
      "source": "bestbuy",
      "store": "Best Buy",
      "price": 198,
      "wasPrice": 398,
      "condition": "new",
      "conditionBasis": "label",
      "inStock": true,
      "url": "https://www.bestbuy.com/product/…/sku/6505727",
      "matchType": "barcode",
      "confidence": 1
    },
    {
      "source": "google",
      "store": "Walmart",
      "seller": "1ShopDirect",
      "price": 198,
      "wasPrice": 287,
      "title": "Sony WH-1000XM5 Noise Canceling Wireless Headphones",
      "condition": "new",
      "conditionBasis": "unlabelled",
      "matchType": "model",
      "confidence": 0.94
    }
  ]
}
```

Every offer has `source`, `store`, `seller`, `price`, `wasPrice`, `currency`, `condition`, `conditionBasis`, `inStock`, `offerType` (`listing`, or `lowest-offer` when Amazon shows only its lowest marketplace offer), `offerCount`, `title`, `url`, `storeId` (SKU, ASIN, Google offer id), `rating`, `reviews`, `matchType` and `confidence`. Set-aside listings (returned in `setAside` with `includeSetAside`) carry a `flag` with the reason: `other colour (…)`, `other variant (/…)`, `bundle or accessory (…)`, `store outside the US`, `price far below the others (…)` or `price far above the others (…)` (against the median), `low confidence (…)` or `condition …` (a condition not among `conditions`). In monitoring, `changes` lists each change with the store, from and to. A barcode no store has comes back as one `not-found` row; when every source failed, a `failed` row.

#### Condition

`condition` is `new`, `renewed` (refurbished, reconditioned, certified pre-owned), `used`, `open-box` or `unknown`, and `conditionBasis` says where it came from:

| `conditionBasis` | Meaning                                                                                                                                                                                |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `label`          | The store's own condition (Best Buy's condition, Google's "Refurbished" or "Pre-owned" label, Amazon's "new offers")                                                                   |
| `title`          | A condition word in the offer's title: "(Renewed)", "Refurbished", "Open Box", "Pre-Owned", "Used - Good", "Like New", also in Spanish                                                 |
| `listing`        | The store's own featured listing, sold new (Amazon's featured price, Target, a data-service record that states no condition)                                                           |
| `unlabelled`     | A Google Shopping listing with no condition label and no condition word in its title: Google labels only items that are not new                                                        |
| `store-listing`  | A Google product card shows the catalog's title; the same store's own listing on the same page, at the same price, states the condition in its title, given as `conditionListingTitle` |
| `none`           | Nothing states it: `unknown` (Amazon's lowest offer over "used & new" offers)                                                                                                          |

A store's label that is not new wins; otherwise a condition word in the title does, so a "(Renewed)" listing is renewed even where Google shows no label; otherwise the same store's own listing at the same price (Google showed StackSocial's open-box Sony WH-1000XM5 at $184.99 under the catalog's title, with no label). `unknown` is never counted as new.

- `lowestPrice` and `lowestPriceStore` are the lowest of every offer kept, whatever its condition, with `lowestPriceCondition`; `lowestNewPrice` and `lowestNewPriceStore` cover confirmed-new offers only. `conditionCounts` counts the offers by condition.
- `mapViolations` lists confirmed-new offers below MAP only, each with its `title`, `condition`, `conditionBasis` and `seller`. Offers below MAP whose condition is unknown are in `mapUnconfirmed`; renewed, used and open-box ones in `mapOtherCondition`. A new offer far below MAP is a violation all the same: nothing is classified by price. In offer rows, `belowMap` is any offer below MAP and `mapViolation` a confirmed-new one.

Every run writes `RUN_SUMMARY` to the key-value store: the outcome (`COMPLETE`, `PARTIAL`, `NO_CHANGES`, `EMPTY` or `FAILED`), products with offers, any source failures, Google requests and charges.

### Pricing

Pay per product with offers and per Google Shopping search.

| Event                                                                                                            | Free and Bronze | Silver | Gold   |
| ---------------------------------------------------------------------------------------------------------------- | --------------- | ------ | ------ |
| Product with offers                                                                                              | $3.00           | $2.70  | $2.40  |
| Google Shopping request (per store searched, per product)                                                        | $4.00           | $3.60  | $3.20  |
| Product with changes (changes only)                                                                              | $2.00           | $1.80  | $1.60  |
| Provider record (an exact barcode match from Target or Best Buy through the data service, delivered as an offer) | $3.00           | $2.70  | $2.40  |
| Provider search (one data-service search that answered: one store, all the run's barcodes)                       | $20.00          | $20.00 | $20.00 |

Prices are per 1,000. With the defaults (an unfiltered search plus Walmart and Target) a product costs about **$15 per 1,000**; Amazon and Best Buy alone cost **$3 per 1,000**. The product event is charged only for a product with offers; Google requests are charged as made, also for a barcode no store knows (one web search for its name, then the Shopping searches). Each run also has a $0.00005 start fee. With `serviceStores`, each store adds one provider search per run ($0.02, flat: it covers the near matches the service returns and the wait) and one provider record for each barcode it sells, delivered as an offer ($0.003): 100 barcodes on Target and Best Buy add at most $0.04 + $0.60. Near matches are not charged, and a search that failed or was blocked charges nothing. A run restarted after a platform migration never charges a record or a search again. Max cost per run counts the search fees and one record per barcode and store before any search starts; barcodes past that are not looked up through the service, with a note.

### Limits

- US stores and US-dollar prices.
- Google Shopping does not look products up by barcode, so its listings are matched by model number or name, as each offer says. Products without a model number (games, toys, drinkware) are matched by name, with lower confidence.
- Amazon sometimes shows only its lowest marketplace offer ("19 used & new offers"), not a featured price: such offers are marked `lowest-offer`. Over "used & new" offers the condition is `unknown`, so unless `used` is among the conditions it is listed but left out of the lowest price and price position; below MAP it is in `mapUnconfirmed`.
- Google shows one price per listing; it does not list every seller of a product in one place, so smaller sellers appear when Google ranks them.
- Target's own API often refuses automated requests, so Target prices come from Google Shopping by default. `target` in `sources` tries Target by barcode first, as a best effort.
- Stock is known for Best Buy; Google listings do not state it.
- Through the data service, a run waits 3 to 5 minutes for Target and Best Buy, and a barcode the store does not sell costs only its share of the search fee. A store that refuses the service's crawler is reported as failed for that run.
- **Nothing found**: a product no source lists still gets one free `recordType: "not-found"` row with a `reason`, and the run succeeds; nothing is charged. A run near its time limit stops starting products, delivers what it checked and gives each product left a free `recordType: "unreadable"` row. Only a run in which every source failed for every product fails.

### Changelog

- **0.3.x, reliability** (2026-10-24): `not-found` and `failed` rows carry a `reason`; input naming no product ends SUCCEEDED with a free `unreadable` row instead of FAILED; a run stops starting products before its time limit and ends with what it checked, never TIMED-OUT. Prices and events unchanged.
- **0.3** (2026-10-16): Offer condition from the title too, and for a Google product card from the same store's own listing at the same price ("(Renewed)", "Open Box", "Pre-Owned"…, in English and Spanish), as `new`, `renewed`, `used`, `open-box` or `unknown`, with `conditionBasis`; unknown is never taken for new. New fields `lowestPriceCondition`, `lowestNewPrice`, `lowestNewPriceStore`, `conditionCounts`, `mapUnconfirmed`, `mapOtherCondition`, and `title`, `condition`, `conditionBasis` in each MAP entry. **Correctness fix: `mapViolations` now lists confirmed-new offers only**; renewed, used and open-box offers below MAP moved to `mapOtherCondition`, unknown ones to `mapUnconfirmed`. A listing whose title says renewed (or used, open box) is now set aside when its condition is not among `conditions` (default `new`). Field names and inputs are unchanged: `refurbished` in `conditions` means `renewed`, and saved monitors keep their offer keys. **Saved monitors:** an offer whose condition is newly detected (from its title or the store's own listing) may show a one-time change on the first run after the update: removed under its old key and new under its condition, or no longer counted when its condition is not among `conditions`.
- **0.2** (2026-10-15): Target and Best Buy by barcode through CleanPull's marketplace data service (`serviceStores`, optional), one search per store for all the run's barcodes, exact barcode matches only. New events: provider record (an exact match delivered, $0.003) and provider search ($0.02 per store per run, only when the search answered). Off by default: runs without it are unchanged.
- **0.1.x** (2026-10-14): Max cost per run (`maxRunCostUsd`), so a scheduled run stays within a budget even without a spending limit.
- **0.1** (October 2026): Amazon and Best Buy by barcode; Google Shopping by store filter for any store, matched by model number or name; set-aside rules for colours, variants, bundles, foreign stores and outlier prices; MAP and own-price checks; changes-only monitoring by store; product and offer outputs.

# Actor input Schema

## `products` (type: `array`):

UPC (12 digits), EAN (13), GTIN-14 or EAN-8, one per line. Amazon, Best Buy and Target are searched by the barcode itself. A product name (for example "Sony WH-1000XM5") is searched on Google Shopping only.

## `sources` (type: `array`):

Where to look. Amazon and Best Buy match the barcode exactly. Google Shopping adds Walmart, Target, eBay and other stores, matched by model number or name. Target by barcode is off by default: Target often refuses automated requests, and its prices come from Google Shopping instead.

## `serviceStores` (type: `array`):

Optional. Look these stores up by barcode through CleanPull's marketplace data service instead of reading them directly: every barcode of the run goes in one search per store, which takes 3 to 5 minutes whatever the number of barcodes. Exact matches only (the store's barcode must equal yours). Billed per exact match delivered (at most one per barcode and store) and per search that answered; see Pricing. Empty: off.

## `googleStores` (type: `array`):

One Google Shopping search per store, filtered to that store, as named on Google Shopping (Walmart, eBay, Home Depot, Lowe's, Newegg, Crutchfield, B\&H Photo…). Default: Walmart and Target. Each store is one Google request.

## `googleNameSearch` (type: `boolean`):

One more Google request per product: finds stores you did not name (smaller shops, marketplace sellers).

## `conditions` (type: `array`):

Offers in other conditions are set aside. The condition comes from the store's label, else a condition word in the offer's title ("(Renewed)", "Open Box", "Pre-Owned"); Google Shopping listings without either are new. Offers whose condition no source states (unknown) are kept, and never counted as new.

## `minConfidence` (type: `number`):

0 to 1. Barcode matches are 1; Google listings with the model number about 0.85–1; listings matched on name words only 0.5–0.9.

## `includeSetAside` (type: `boolean`):

Also return the Google listings that were set aside (another colour, a price far from the others, low confidence, another condition), with the reason.

## `mapPrices` (type: `object`):

Optional: {"barcode": price}. Each product lists the offers below its MAP, by how much, with links.

## `myPrices` (type: `object`):

Optional: {"barcode": price}. Each product says how many offers are cheaper than yours.

## `monitorMode` (type: `boolean`):

Schedule the same input: after the first run, only products whose offers changed are returned, with what changed.

## `monitorName` (type: `string`):

Keeps separate watches apart: each name remembers its own last prices.

## `changeTypes` (type: `array`):

Which changes count.

## `minPriceChangePercent` (type: `number`):

Smaller price moves are not reported.

## `maxRunCostUsd` (type: `number`):

Optional. Stop starting new products once a run's charges, plus what the products in progress could still cost, would pass this. Use it for scheduled runs, which may have no spending limit of their own. Empty: only the run's spending limit applies.

## `outputFormat` (type: `string`):

Product records carry all offers, the lowest price and checks; offer rows suit a spreadsheet.

## `fields` (type: `array`):

Optional: return only these fields.

## `maxConcurrency` (type: `integer`):

How many products are checked in parallel.

## `proxyConfiguration` (type: `object`):

Optional. The actor picks proxies itself; set one only to use your own.

## Actor input object example

```json
{
  "products": [
    "027242923232",
    "045496590475",
    "017817846141"
  ],
  "sources": [
    "amazon",
    "bestbuy",
    "google"
  ],
  "serviceStores": [],
  "googleStores": [
    "Walmart",
    "Target"
  ],
  "googleNameSearch": true,
  "conditions": [
    "new"
  ],
  "minConfidence": 0.7,
  "includeSetAside": false,
  "mapPrices": {},
  "myPrices": {},
  "monitorMode": false,
  "monitorName": "default",
  "changeTypes": [
    "new-offer",
    "offer-removed",
    "price-down",
    "price-up",
    "stock",
    "new-lowest"
  ],
  "minPriceChangePercent": 1,
  "outputFormat": "products",
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

One record per product (or per offer with outputFormat "offers"); products with no offers are listed as not-found.

## `products` (type: `string`):

No description

## `offers` (type: `string`):

No description

## `map` (type: `string`):

No description

## `summary` (type: `string`):

Outcome (COMPLETE, PARTIAL, NO_CHANGES, EMPTY, FAILED), counts, source failures, Google requests and charges.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "products": [
        "027242923232",
        "045496590475",
        "017817846141"
    ],
    "googleStores": [
        "Walmart",
        "Target"
    ],
    "mapPrices": {},
    "myPrices": {}
};

// Run the Actor and wait for it to finish
const run = await client.actor("cleanpull/barcode-price-checker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "products": [
        "027242923232",
        "045496590475",
        "017817846141",
    ],
    "googleStores": [
        "Walmart",
        "Target",
    ],
    "mapPrices": {},
    "myPrices": {},
}

# Run the Actor and wait for it to finish
run = client.actor("cleanpull/barcode-price-checker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "products": [
    "027242923232",
    "045496590475",
    "017817846141"
  ],
  "googleStores": [
    "Walmart",
    "Target"
  ],
  "mapPrices": {},
  "myPrices": {}
}' |
apify call cleanpull/barcode-price-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cleanpull/barcode-price-checker"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/UZQoy6kifBRcF81UN/builds/Kp30cDU4vEUr8vPfH/openapi.json
