# Company API

Search, look up and list signals on any Swiss company, with the same filters and rows as the directory.

Three routes over the Swiss company register, on a bearer key holding `companies:read`.

```bash
curl -s -H 'Authorization: Bearer pxk_…' \
  'https://prospex.ch/api/v1/companies?q=machining&canton=VD&size_band=small'

curl -s -H 'Authorization: Bearer pxk_…' 'https://prospex.ch/api/v1/companies/12345'
curl -s -H 'Authorization: Bearer pxk_…' 'https://prospex.ch/api/v1/companies/12345/signals'
```

Every route spends the daily row budget: one row per company or per signal returned.

Any valid company id returns its data. Markets and watches answer **404** for another account's object.

## Routes

| Name | Path |
| --- | --- |
| company_search | /api/v1/companies |
| company_detail | /api/v1/companies/\<str:company_id> |
| company_signals | /api/v1/companies/\<str:company_id>/signals |

## Search parameters

| Parameter | Meaning |
| --- | --- |
| q | Free text. Matches the name, the registered purpose, the UID and the address. |
| canton | Two-letter canton codes, repeated or comma-separated. |
| sector | Sector group keys. See the list below. |
| size_band | `micro`, `small`, `mid` or `large`. |
| audience | `b2b`, `b2c`, `mixed` or `no_market`. |
| followed | `1` to restrict to companies you follow. |
| limit | Rows per page, up to 100. |
| cursor | Opaque. Follow `next_url` instead of building one. |

An unrecognized parameter answers **400 `unknown_parameter`**. A value outside a parameter's vocabulary answers **400 `invalid_parameter`** and names the accepted set.

## Vocabularies

**canton**

AG, AI, AR, BE, BL, BS, FR, GE, GL, GR, JU, LU, NE, NW, OW, SG, SH, SO, SZ, TG, TI, UR, VD, VS, ZG, ZH

**sector**

tech_digital, professional, finance, real_estate, retail, industry, construction, hospitality, health, transport, admin_support, other_public

**size_band**

micro, small, mid, large

**audience**

b2c, b2b, mixed, no_market

## A row

| Field | Type | Meaning |
| --- | --- | --- |
| company_id | integer | The Prospex company id. Stable. |
| company_name | string | The registered name, as the register writes it. |
| company_url | string | The company's page in Prospex. |
| company_tagline | string | One line saying what the company does. Empty when unknown. |
| company_canton | string | Two-letter code of the registered office. |
| company_city | string | The commune of the registered office. |
| company_sector | string | The NOGA division, as a phrase. |
| company_sector_group | string | The macro-sector key, for grouping. |
| company_audience | string | Who the company sells to. |
| company_employee_size | string | The headcount bucket. Empty when unknown. |
| signal_count | integer | Visible signals on this company, live-counted. |
| latest_signal_date | string\|null | The most recent event date, ISO. |
| followed | boolean | Whether you follow this company. |

Search relevance is per-query, so the response carries a band word, never a score.

`version` is `1` on the company routes and `1` on the signal route. They are separate payload contracts and version independently.

## One company's signals

| Parameter | Meaning |
| --- | --- |
| since | ISO date or datetime. Only signals recorded after it. |
| type | Signal types, repeated or comma-separated. |
| limit | Rows per page, up to 100. |
| cursor | Opaque, keyset-based. Follow `next_url` instead of building one. |

A row here is a signal-feed row, field for field. Use `has_more` and `next_url` to page through results.

## Pagination, and the ceiling on search

Follow `next_url`. It is absolute, carries every parameter you sent, and carries no credential: the key stays in the header, so the URL is safe to log and to paste into a ticket.

Search returns at most 2,000 results for one query. Asking past that answers **400 `window_exceeded`**. Narrow the query, or read a market's companies at `/api/v1/markets/<id>/companies`, which has no ceiling.

If the search index is unreachable you get **503 `search_unavailable`**.

Default page size 25, maximum 100.
