# Market feed

One market's companies as JSON or CSV, on a revocable URL that needs no session, with the market's own reasons on every row.

One revocable URL per market, in two formats, found on the market's Connect page. The token in the path is the whole credential, with no session and no header, so treat the URL the way you treat a password. Regenerating it revokes the previous one immediately.

```bash
curl -s 'https://prospex.ch/app/markets/feed/<token>.json?limit=200'
curl -s -o market.csv 'https://prospex.ch/app/markets/feed/<token>.csv'
```

Each row is one company, with the market's reasons and recent events attached.

Every response carries `Cache-Control: no-store`.

## Parameters

| Parameter | Meaning |
| --- | --- |
| tab | `core` (the default) or `explore`. Core is the market's answer to who to sell to. Explore is the wider bucket you have not decided about yet. |
| limit | Rows per page, up to 500. Ignored by the CSV, which streams the whole bucket in one response. |
| cursor | Opaque, and issued by this feed. Follow `next_url` rather than building one. |

Extra parameters are ignored.

## The envelope

| Key | Type | Meaning |
| --- | --- | --- |
| version | integer | The payload contract. `1` today. |
| market | object | The market's id, its name, and when it was last refreshed. |
| generated_at | string | ISO 8601 UTC, the moment this page was built. |
| count | integer | Rows in `data` on this page. |
| total | integer | Rows in the served bucket, across every page. |
| has_more | boolean | Whether a page follows this one. |
| next_url | string | The next page, absolute and carrying every parameter you sent. Empty on the last page. |
| usage | object | `rows_today` and `daily_limit`, so a workflow can stop before the feed stops it. |
| data | array | The companies. One flat object per company. |

`version` is bumped when a field changes meaning or leaves. A new field does not bump it.

## Pagination

Follow `next_url`. It is absolute and carries every parameter you sent.

The cursor carries the build it was issued under. A market's order changes only when a build refreshes it, so a cursor from an older build answers **400 `invalid_parameter`** and asks you to start again.

The CSV takes no cursor. It streams up to 10,000 rows in one response and is capped by what remains of the day's row budget.

## A row

Flat, with a `company_` prefix on the registry facts:

| Field | Meaning |
| --- | --- |
| fit | The stored word. `fit_label` is the same judgement in the language of the workspace, so a filter written against `fit` survives a retranslation. |
| reasons | Why this company is in the market, in the same words the workspace shows. |
| missing | What the market asked about and Prospex does not know for this company. A blank field means missing data, not a failed criterion. Useful for deciding what to enrich. |
| in_crm | Whether your connected CRM already holds this company. Populated from the CRM mirror, so it is as current as the last mirror pass. |
| signals | Up to 3 recent events, newest first, each with its type, its date, its title and a link that opens on the event itself. Suppressed events are absent. |

Position in the list is the rank.

## The CSV columns

One line per company, in this order. The second column is the JSON key a Clay column or an n8n expression maps:

| Header | From |
| --- | --- |
| Company ID | company_id |
| Company | company_name |
| Company UID | company_uid |
| Company URL | company_url |
| Website | company_website |
| Domain | company_domain |
| Tagline | company_tagline |
| City | company_city |
| Canton | company_canton |
| Audience | company_audience |
| Employee Size | company_employee_size |
| NOGA Division | company_sector_code |
| Sector | company_sector |
| Bucket | bucket |
| Fit | fit |
| Fit Label | fit_label |
| Reasons | reasons_text |
| Missing | missing_text |
| Kept | pinned |
| In CRM | in_crm |
| Signal Count | signal_count |
| Latest Signal | latest_signal_date |
| Signal Titles | signal_titles |
| Signal IDs | signal_ids |

Four of those keys exist only in the CSV, because the JSON field they come from is an array and a cell cannot nest. `reasons_text` joins with a pipe, `missing_text` with a comma, and the two signal columns carry the titles and the ids of the same recent events.

## Refusals

| Status | error | When |
| --- | --- | --- |
| 404 | unknown_token | No feed answers this URL. Also the answer for a feed switched off and for a market that has been deleted, so a response never confirms that a token existed. |
| 402 | subscription_required | The market owner's subscription is not active. The body carries a billing URL. |
| 400 | invalid_parameter | A cursor this feed did not issue, or one issued before the market was last refreshed. Start again without a cursor. |
| 429 | daily_row_limit | The account has taken its rows for the day. `Retry-After` points at the reset. |
| 503 | feed_disabled | The surface is switched off globally. |

The same five codes come out of the [project feed](https://prospex.ch/docs/feed/).

## No push

There is no webhook on a market.

For push delivery, use a [watch](https://prospex.ch/docs/watch-a-list/) (email) or a Prospect project ([webhooks](https://prospex.ch/docs/webhooks/)).
