# CJ Affiliate API - Commission Junction Products & Feeds (`viralanalyzer/cj-affiliate-products`) Actor

Query CJ.com (Commission Junction) GraphQL API for affiliate products, 15k+ shopping product feeds, finance credit cards, travel experiences. You provide your own PAT + CID. Multi-vertical discovery.

- **URL**: https://apify.com/viralanalyzer/cj-affiliate-products.md
- **Developed by:** [viralanalyzer](https://apify.com/viralanalyzer) (community)
- **Categories:** Lead generation, E-commerce
- **Stats:** 3 total users, 0 monthly users, 96.4% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 item scrapeds

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

## 💼 CJ Affiliate (Commission Junction) — Products, Feeds & Advertisers API (BYOC)

> 🔗 [View on Apify Store](https://apify.com/viralanalyzer/cj-affiliate-products) | 🇺🇸 English | [🇧🇷 Português](#português)

Query the **CJ.com GraphQL API** at `ads.api.cj.com/query` for affiliate products, shopping feeds, advertiser discovery, finance credit card products, and travel experiences. **BYOC (Bring Your Own Credentials)** — you provide your CJ Personal Access Token (PAT) + Company ID (CID). Six query types covering 15k+ advertiser feeds.

### ✨ Features

- **Official CJ GraphQL endpoint** — `https://ads.api.cj.com/query`, Bearer PAT auth (no OAuth flow)
- **6 query types** covering discovery and search:
  - `shoppingProductFeeds` — list ALL shopping feeds available to the publisher (15k+ advertisers, no join required)
  - `productFeeds` — generic feed discovery
  - `products` — keyword search across ALL products (requires joined advertisers)
  - `shoppingProducts` — keyword search restricted to Shopping vertical (requires joined advertisers)
  - `financeCreditCardProducts` — credit card listings with APR/fees/credit-score-needed
  - `travelExperienceProducts` — travel & experience products with location + duration
- **Keyword filter** — array of keywords (applied to product/shopping/travel queries)
- **Advertiser ID filter** — narrow to specific advertisers found via `shoppingProductFeeds`
- **Pagination** — `maxResults` + `offset` (CJ API hard cap 1000 per request)
- **Anti-bot-immune** — official API, no scraping
- **NEVER 0 ITEMS guard** — actor fails with diagnostic message naming the queryType + likely cause

### 🔑 BYOC setup (one-time, free, ~10 min)

1. Sign in at https://www.cj.com (you must have a CJ Publisher account; sign-up is free)
2. Go to https://developers.cj.com and click **Create Personal Access Token**
3. Copy the **PAT** (one-time display) and paste into the actor input as `accessToken`
4. Get your **Company ID (CID)** at https://members.cj.com > Account > Account Information (~7 digits, e.g. `7957587`)
5. Paste the CID into `companyId`

> **Note**: `products` and `shoppingProducts` queries only return products from advertisers you have **joined**. Use `shoppingProductFeeds` for cold discovery — it lists every advertiser feed in the CJ network regardless of join status.

### 📥 Input

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `accessToken` | string (secret) | **Yes** | — | Your CJ Personal Access Token |
| `companyId` | string | **Yes** | — | Your CJ Publisher CID (~7 digits) |
| `queryType` | enum | No | `shoppingProductFeeds` | One of: `shoppingProductFeeds`, `productFeeds`, `products`, `shoppingProducts`, `financeCreditCardProducts`, `travelExperienceProducts` |
| `keywords` | string\[] | No\* | `[]` | Search keywords (for `products` / `shoppingProducts` / `travelExperienceProducts`) |
| `advertiserIds` | string\[] | No | `[]` | Filter to specific advertiser IDs (discover via `shoppingProductFeeds` first) |
| `maxResults` | integer | No | `25` | Items per request (1-1000) |
| `offset` | integer | No | `0` | Pagination offset |

\*Keywords are required for `products`, `shoppingProducts`, and `travelExperienceProducts`; ignored for feed/finance queries.

#### Input example (JSON) — discovery mode

```json
{
  "accessToken": "your_cj_pat_here",
  "companyId": "7957587",
  "queryType": "shoppingProductFeeds",
  "maxResults": 100,
  "offset": 0
}
```

#### Input example (JSON) — product search

```json
{
  "accessToken": "your_cj_pat_here",
  "companyId": "7957587",
  "queryType": "shoppingProducts",
  "keywords": ["smart watch", "fitness tracker"],
  "advertiserIds": ["3651573", "3508051"],
  "maxResults": 50
}
```

### 📤 Output

Each record carries the `queryType` flag plus type-specific fields. Example `shoppingProductFeeds` output:

```json
{
  "queryType": "shoppingProductFeeds",
  "advertiserId": "3651573",
  "advertiserName": "Best Buy",
  "feedName": "Best Buy US Shopping Feed",
  "feedLanguage": "en",
  "feedCurrency": "USD",
  "feedLastUpdated": "2026-05-14T03:00:00Z",
  "feedProductCount": 145329,
  "feedTargetCountry": "US",
  "adId": "12345678",
  "scrapedAt": "2026-05-15T14:30:00Z"
}
```

Example `financeCreditCardProducts` output:

```json
{
  "queryType": "financeCreditCardProducts",
  "advertiserId": "4504329",
  "advertiserName": "American Express",
  "productId": "amex_blue_cash",
  "title": "Blue Cash Everyday® Card",
  "cardType": "Cash Back",
  "creditScoreNeeded": "Good to Excellent (670-850)",
  "annualMemFee": "$0",
  "purchaseIntroApr": "0% intro APR for 15 months",
  "regularApr": "19.24% - 29.99% Variable",
  "foreignTransactionFee": "2.7%",
  "link": "https://www.tkqlhce.com/click-...",
  "imageLink": "https://www.americanexpress.com/.../card.png"
}
```

### ✅ Capabilities & Limits

Stated up front, so you do not pay a run to find out.

**Built here:** `gtin`, `upc`, `mpn`, `condition`, `availability` and `sourceFeedId` exist in the output schema but always come back null - no GraphQL query the actor builds ever selects them. With `queryType: "products"` the type-specific fields sit inside an inline `... on Shopping` fragment, so travel and finance rows return `productType`, `brand` and `imageLink` empty. Use `shoppingProducts` when you need those fields.

| Input / feature | Supported | Notes |
|---|---|---|
| **Your own CJ credentials** | ⚠️ **Required** | `accessToken` (Personal Access Token from developers.cj.com) and `companyId` (Publisher CID). There is no public mode |
| Query type | ✅ | `queryType` selects which CJ GraphQL query runs |
| Keyword search | ✅ | `keywords` — applies to product-type queries |
| Advertiser filter | ✅ | `advertiserIds`; get IDs from the shopping-product-feed query |
| Pagination | ✅ | `offset` plus `maxResults` — CJ caps at **1,000 items per request** |
| Advertisers you have not joined | ⚠️ | visibility follows what CJ exposes to your publisher account |
| Commission / earnings reports | ❌ | this reads product and feed data, not your payout reports |
| Works without a CJ account | ❌ | credentials are the entire mechanism |

### 💰 Pricing

**$0.005 per result returned** (`item-scraped`), Apify platform usage of the run is included — you are not billed separately for compute
or proxy.

Pay-per-event (`item-scraped`): charged once per result successfully returned by the CJ API. Zero-result queries do **not** charge.

### 🚀 Use cases

- **Cold advertiser discovery** — surface 15k+ CJ feeds without joining anything first (use `shoppingProductFeeds`)
- **Credit card affiliate research** — APR / annual-fee comparison for finance publishers
- **Travel product catalog** — pull experience inventory with location + duration
- **Joined-advertiser product search** — pull a fresh product feed for advertisers you already work with
- **Competitive intel** — discover which advertisers in your vertical have active feeds (and how big they are)

### ⚠️ Common errors

Every code below appears at the **top of the run page** (status message) — you do not
need to open the log. **None of them charges you**: this Actor only bills `item-scraped`
for records it actually delivered.

| Code | Cause | Fix |
|---|---|---|
| `CREDENTIALS_REQUIRED` (run **succeeds**) | `accessToken` and/or `companyId` left empty | Fill both — see BYOC setup above |
| `CJ_AUTH_REJECTED` (HTTP 401/403) | PAT expired/revoked, or wrong CID | Regenerate the PAT at developers.cj.com; confirm the CID at members.cj.com > Account > Company Information |
| `CJ_GRAPHQL_ERROR` | CJ accepted the token but refused the query — usually a CID that is not yours, or a `queryType` your account cannot access | Re-check `companyId`; try `shoppingProductFeeds`, which needs no advertiser join |
| `CJ_RATE_LIMITED` (HTTP 429) | Too many requests for this token | Wait a few minutes |
| `CJ_UNAVAILABLE` (HTTP 5xx) / `CJ_NON_JSON` | CJ's API is down or answered garbage | Retry later — nothing you can fix |
| `DIAGNOSTIC_GUIDE` (run **succeeds**) | CJ returned 0 records for your filters | Read the diagnostic record — it lists the likely causes |
| `ACTOR_ERROR` | A bug on our side | Report it on the Issues tab |

> `products` and `shoppingProducts` only return advertisers you have **already joined**.
> `shoppingProductFeeds` is the discovery query that works without joining anything.

### 🔒 Privacy

Your PAT is sent directly to `ads.api.cj.com` over HTTPS. We never store, log, or proxy it through our servers. Mark `accessToken` as secret in the Apify input form.

### 📚 Related actors

- [Impact.com Affiliate API](https://apify.com/viralanalyzer/impact-affiliate-network) — Impact Publisher API (BYOC)
- [Rakuten Affiliate Merchants](https://apify.com/viralanalyzer/rakuten-affiliate-merchants) — Rakuten API (BYOC)
- [Awin Multi-Merchant](https://apify.com/viralanalyzer/awin-multi-merchant-affiliate) — Awin Publisher API (BYOC)
- [Etsy Product Intelligence](https://apify.com/viralanalyzer/etsy-product-intelligence) — Etsy Open API v3 (BYOC)
- [ClickBank Marketplace Intelligence](https://apify.com/viralanalyzer/clickbank-marketplace-intelligence) — ClickBank digital products

### 🆕 Changelog

- **v1.0** (2026-05-14): Initial release. 6 query types (shoppingProductFeeds / productFeeds / products / shoppingProducts / financeCreditCardProducts / travelExperienceProducts). Bearer PAT auth. NEVER 0 ITEMS guard with 4-cause diagnostic.

***

### Português

## 💼 CJ Affiliate (Commission Junction) — API de Produtos, Feeds e Advertisers (BYOC)

> 🔗 [Ver na Apify Store](https://apify.com/viralanalyzer/cj-affiliate-products)

Consulta a **API GraphQL da CJ.com** em `ads.api.cj.com/query` para produtos afiliados, feeds de shopping, descoberta de advertisers, cartões de crédito e produtos de viagem. **BYOC (Bring Your Own Credentials)** — você fornece seu PAT (Personal Access Token) + CID (Company ID) da CJ. Seis tipos de query cobrindo 15k+ feeds de advertisers.

#### ✨ Recursos

- **Endpoint oficial CJ GraphQL** — Bearer PAT, sem OAuth
- **6 tipos de query**:
  - `shoppingProductFeeds` — lista TODOS os feeds disponíveis (15k+, sem precisar fazer "join")
  - `productFeeds` — descoberta genérica
  - `products` — busca por keyword em todos os produtos (exige advertisers joined)
  - `shoppingProducts` — busca apenas no vertical Shopping (exige advertisers joined)
  - `financeCreditCardProducts` — cartões com APR/anuidade/score
  - `travelExperienceProducts` — viagens e experiências com local + duração
- **Filtro de keywords** + filtro por **advertiserIds**
- **Paginação** — `maxResults` + `offset` (limite CJ 1000 por requisição)
- **Imune a anti-bot** — API oficial
- **NUNCA 0 ITENS** — falha com mensagem diagnóstica nomeando o queryType e a causa provável

#### 🔑 Setup BYOC (uma vez, grátis, ~10 min)

1. Crie conta Publisher em https://www.cj.com (grátis)
2. Em https://developers.cj.com clique **Create Personal Access Token**
3. Copie o **PAT** (exibido uma única vez) e cole no input em `accessToken`
4. Encontre seu **CID** em https://members.cj.com > Account > Account Information (~7 dígitos)
5. Cole o CID em `companyId`

> `products` e `shoppingProducts` só retornam advertisers em que você fez **join**. Para descoberta a frio, use `shoppingProductFeeds`.

#### 📥 Input

| Parâmetro | Tipo | Obrigatório | Default | Descrição |
|---|---|---|---|---|
| `accessToken` | string (secret) | **Sim** | — | Seu PAT da CJ |
| `companyId` | string | **Sim** | — | Seu CID Publisher (~7 dígitos) |
| `queryType` | enum | Não | `shoppingProductFeeds` | Um dos 6 acima |
| `keywords` | string\[] | Não\* | `[]` | Para queries de busca |
| `advertiserIds` | string\[] | Não | `[]` | Filtro por advertiser |
| `maxResults` | integer | Não | `25` | Itens por request (1-1000) |
| `offset` | integer | Não | `0` | Paginação |

#### 💰 Cobrança

Pay-per-event `item-scraped`: cobrado por resultado retornado pela API. Query com zero resultado **não cobra**.

#### 🚀 Casos de uso

- Descoberta de advertisers (15k+ feeds sem precisar joinar)
- Pesquisa de afiliados de finanças (cartões de crédito)
- Catálogo de produtos de viagem
- Atualização de feed de advertisers que você já trabalha
- Inteligência competitiva por vertical

#### ⚠️ Erros comuns

Todo código abaixo aparece no **topo da página do run**, sem precisar abrir o log.
**Nenhum deles cobra**: este Actor só fatura `item-scraped` por registro entregue.

- `CREDENTIALS_REQUIRED` (run com **sucesso**): `accessToken` e/ou `companyId` vazios — preencha os dois
- `CJ_AUTH_REJECTED` (HTTP 401/403): PAT expirado/revogado, ou CID errado — regere o PAT em developers.cj.com e confira o CID em members.cj.com > Account > Company Information
- `CJ_GRAPHQL_ERROR`: a CJ aceitou o token mas recusou a consulta — normalmente um `companyId` que não é o seu, ou um `queryType` sem acesso na sua conta
- `CJ_RATE_LIMITED` (HTTP 429): espere alguns minutos
- `CJ_UNAVAILABLE` (HTTP 5xx) / `CJ_NON_JSON`: a API da CJ caiu — nada a fazer do seu lado
- `DIAGNOSTIC_GUIDE` (run com **sucesso**): a CJ devolveu 0 registros para os seus filtros — leia o registro de diagnóstico
- `ACTOR_ERROR`: bug do nosso lado — reporte na aba Issues

> `products` e `shoppingProducts` só devolvem advertisers em que você **já se afiliou**.
> `shoppingProductFeeds` é a consulta de descoberta e não exige afiliação nenhuma.

#### 🔒 Privacidade

PAT enviado diretamente para `ads.api.cj.com` via HTTPS. Não armazenamos nem logamos credenciais.

#### 📚 Actors relacionados

- [Impact.com Affiliate API](https://apify.com/viralanalyzer/impact-affiliate-network)
- [Rakuten Affiliate Merchants](https://apify.com/viralanalyzer/rakuten-affiliate-merchants)
- [Awin Multi-Merchant](https://apify.com/viralanalyzer/awin-multi-merchant-affiliate)
- [Etsy Product Intelligence](https://apify.com/viralanalyzer/etsy-product-intelligence)
- [ClickBank Marketplace Intelligence](https://apify.com/viralanalyzer/clickbank-marketplace-intelligence)

#### 🆕 Changelog

- **v1.0** (2026-05-14): release inicial, 6 query types, NUNCA 0 ITENS guard.

# Actor input Schema

## `accessToken` (type: `string`):

Your CJ Personal Access Token from developers.cj.com. REQUIRED. Bearer auth used directly (no OAuth flow).

## `companyId` (type: `string`):

Your CJ Publisher CID (~7 digits, e.g. 7957587). Found at members.cj.com > Account Information. REQUIRED for ALL queries.

## `queryType` (type: `string`):

Which CJ GraphQL query to run

## `keywords` (type: `array`):

Search keywords. Applies to 'products', 'shoppingProducts', 'travelExperienceProducts'. Leave empty for non-product queries.

## `advertiserIds` (type: `array`):

Filter results to specific advertiser IDs. Get IDs from queryType=shoppingProductFeeds first.

## `maxResults` (type: `integer`):

Maximum items to return (CJ API limit per request: 1000)

## `offset` (type: `integer`):

Skip N items before returning results (for pagination)

## Actor input object example

```json
{
  "queryType": "shoppingProductFeeds",
  "keywords": [],
  "advertiserIds": [],
  "maxResults": 10,
  "offset": 0
}
```

# Actor output Schema

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

Dataset of all results; each item follows the dataset schema.

# 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 = {
    "maxResults": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("viralanalyzer/cj-affiliate-products").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 = { "maxResults": 10 }

# Run the Actor and wait for it to finish
run = client.actor("viralanalyzer/cj-affiliate-products").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 '{
  "maxResults": 10
}' |
apify call viralanalyzer/cj-affiliate-products --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,viralanalyzer/cj-affiliate-products"
        }
    }
}
```

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/UJak4efg8I1BeNYkx/builds/gZk75SOWG0D3flaOv/openapi.json
