List changes
An append-only feed of catalogue mutations, so a mirror can resync without refetching everything.
/v1/changes1 creditfree planCache-Control: public, max-age=30
Objects returned
Written by database triggers, not by application code: nothing can mutate a row without appearing here, and ids are monotonic, so a single integer is a complete sync position. Each entry names the kind, the public entity_id, the op (INSERT, UPDATE, DELETE) and the version the row reached.
Follow links.next until meta.has_more is false, store meta.next_since, and poll. meta.watermark is the newest id in the feed and meta.behind how far your cursor is from it. meta.oldest_available matters on a first sync: if your stored position is older than it, the feed can no longer replay the gap and a full refetch is the honest answer.
Query parameters
| Name | Type | Default | Description |
|---|---|---|---|
since | integer | 0 | The meta.next_since of your previous page. 0, or omitted, starts from the oldest entry still available. |
kind | string | — | Comma-separated entity kinds: CARD, SET, SEALED, PRICE, IMAGE. |
limit | integer | 50 | Rows per page, 1 to 250. Above 250 you get LIMIT_EXCEEDED — follow links.next instead of raising it. |
Headers
| Name | Type | Default | Description |
|---|---|---|---|
X-Api-Key required | string | — | Your API key. Authorization: Bearer <key> is accepted as an alias. |
If-None-Match | string | — | Send back the ETag you stored. The API returns a strong ETag on every catalogue response, and a 304 is a header exchange: no body, no database row read. |
Example request
curl -s -G "https://api.pokemontcgapi.com/v1/changes" \
--data-urlencode "limit=2" \
-H "X-Api-Key: $PTCG_API_KEY"Example response
200 OK · Cache-Control: public, max-age=30
{
"data": [
{
"id": 1,
"kind": "SET",
"entity_id": "sv2a",
"op": "INSERT",
"version": 1,
"changed_at": "2026-09-02T12:39:35.894Z"
},
{
"id": 2,
"kind": "SET",
"entity_id": "svln",
"op": "INSERT",
"version": 1,
"changed_at": "2026-09-02T12:39:35.894Z"
}
],
"meta": {
"count": 2,
"has_more": true,
"next_since": 2,
"watermark": 116242,
"oldest_available": 1,
"behind": 116240
},
"links": {
"next": "https://api.pokemontcgapi.com/v1/changes?limit=2&since=2"
}
}Errors
Every error body carries error.code, error.message and error.request_id. Switch on the code, never on the message.
| Status | Code | When |
|---|---|---|
| 401 | MISSING_API_KEY | No X-Api-Key header and no bearer token on a route that requires one. |
| 401 | INVALID_API_KEY | The key does not match any account. |
| 400 | INVALID_PARAMETER | A query parameter has the wrong type or an unsupported value — a non-integer limit, an unknown lang, an unknown region, a sort key that is not sortable. |
| 400 | LIMIT_EXCEEDED | limit is above 250, or a batch request carries more than 100 ids. |
The full taxonomy, with what to do about each code, is on the errors page.