# Sigpik Free Public API

Read selected product rankings and signals as JSON. No registration, subscription, API key or Authorization header is required. Any HTTP client can use these endpoints and combine the results with other data or services.

## Requests

```sh
curl "https://sigpik.com/api/public/v1/rankings?locale=en"
curl "https://sigpik.com/api/public/v1/signals?locale=zh-CN"
```

```js
const response = await fetch('https://sigpik.com/api/public/v1/rankings?locale=en');
if (!response.ok) {
  throw new Error(`HTTP ${response.status}; retry after: ${response.headers.get('Retry-After') ?? 'see response'}`);
}
const data = await response.json();
console.log(data.edition, data.stale, data.items);
```

The only parameter is `locale`: `en` (default) or `zh-CN`. Both languages contain the same record set. Unknown parameters and repeated `locale` parameters return 400. No pagination, arbitrary filters, product lookup or historical edition queries are available.

## Shared response fields

| Field | Meaning |
| --- | --- |
| `version` | Response contract version, currently `1`. |
| `kind` | `rankings` or `signals`. |
| `edition` | Publication day in UTC. |
| `published_at` | Selection generation timestamp; not the observation time of its records. |
| `stale` | Whether the current daily publication is delayed. Decide whether to use it based on its age. |
| `locale` | Response language. |
| `selection` | Selection method identifier. |
| `max_items` | Maximum records per selection, currently 5. |
| `items` | Selected records; fewer than five or an empty array is valid. |
| `items[].id` | Stable record ID, usable for deduplication. |
| `items[].product` | Product `name`, `slug` and detail `url`. |
| `source_url` | Corresponding ranking or signals page. |
| `documentation_url` | Developer documentation. |

## Selected rankings

`GET /api/public/v1/rankings`

At most five products ranked by positive absolute traffic gain between the latest complete comparable months. Each month must have at least 1,000 estimated visits. These are monthly estimates, even though the selection is published daily.

| Record field | Meaning |
| --- | --- |
| `rank` | Position in the selected ranking. |
| `period.current_month` | Current comparison month. |
| `period.previous_month` | Previous comparison month. |
| `estimated_visits` | Estimated visits in the current month. |
| `previous_estimated_visits` | Estimated visits in the previous month. |
| `visits_change` | Absolute increase in estimated visits. |
| `growth_rate` | Growth ratio: `0.314` means `31.4%`. |

## Selected signals

`GET /api/public/v1/signals`

At most five confirmed, published signals with an importance score of at least 80, one per product. Selection considers up to 200 recent observations in the seven UTC days before the edition cutoff, ordered by importance and observation time. It is a selected digest, not a complete or real-time event stream.

The response includes `observation_window.start` and `observation_window.end` for the selection window.

| Record field | Meaning |
| --- | --- |
| `type` | Signal type. |
| `title`, `summary` | Public signal label and explanation. |
| `direction` | `up`, `down`, `neutral`, `mixed` or `unknown`. |
| `before`, `after` | Scalar `value` and `unit`, or null when unavailable. The unit can also be null. |
| `observed_at` | Observation timestamp. |
| `published_at` | Signal publication timestamp. |
| `period.start`, `period.end` | Measurement period, nullable. |

## Freshness, caching and errors

One shared edition is generated per UTC day. Only the latest selection is available. Clients do not trigger data collection or investigations. Public requests do not consume account API quotas.

Check `published_at` and `stale`. If an update is delayed, the last successful selection is retained for at most 48 hours; older or unavailable data returns 503. Do not invent records when `items` is empty.

Read once daily. Edge rate limiting allows 120 requests per IP per minute; clients sharing an IP also share that limit. HTTP caching is five minutes. Store the response `ETag` and send it as `If-None-Match` on subsequent reads to receive 304 when unchanged. A 304 has no JSON body; reuse your previous response.

| Status | Action |
| --- | --- |
| 400 | Correct the unsupported or duplicate parameter. |
| 429 | Follow `Retry-After` before retrying. |
| 503 | Follow `Retry-After` and try again later. |

## Scope

The public selection is identical for all clients, including authenticated clients. These endpoints do not expose the full catalog, historical editions, raw evidence, a keyword database or investigation reports. Recipients may retain previously received selections. Existing paid research and personal watchlist webhook permissions are unchanged.

[Developer documentation](https://sigpik.com/developers#public-api) · [OpenAPI](https://sigpik.com/docs/public-api/openapi.json)

## 中文说明

公共免费 API 无需注册或 Key，通过普通 HTTP 请求返回 JSON。提供最多 5 条精选榜单和 5 条精选异动，用户可以自行组合到任何应用、脚本或自动化流程中。

只支持语言参数，所有用户获取相同记录集合。不提供翻页、任意筛选、历史版本或全量导出。数据不足时允许为空；请检查数据周期、`published_at` 和 `stale`，并遵循频控与错误响应。榜单使用月度估算数据，精选异动不是实时完整事件流。
