Skip to main content
The changes feed lists every record that changed, in the order changes were published. With a stored cursor, you can keep your own copy of one or more registers current by polling it.

How the feed works

  • Each item is a change with type: "trademark.changed" and the record as it is when you read the page. If a record changed twice since your last poll, you get it once, in its latest state.
  • created_at is when the change was published to the feed. Items are ordered by it, and several items can share one timestamp.
  • trademark is a summary. Add include=full (with limit up to 25) to get full records, or fetch the ones you need with batch retrieve.
  • next_cursor is never null. It is your position in the feed; store it after every page.
  • has_more: false means you have everything published before complete_through. Poll again later with the same cursor.
  • Ignore item types you do not know. trademark.removed is reserved for a later version.

Subscribe

Choose your scope: the registers you want, as jurisdiction (up to 20 codes), or no jurisdiction for every register. Then call the feed once without since or cursor. This subscribes from now: you get an empty page and a cursor.
Send the same jurisdiction on every later call. A cursor is bound to its scope; a different scope gets 400 cursor-mismatch. To change scope, start a new subscription (and load any new register as below).

Initial load

The feed only carries changes. To start a copy, combine it with search, in this order:
  1. Take a feed cursor first, by subscribing as above, and store it.
  2. Copy the current state of your scope with a search (for example jurisdiction=AD,AL), fetching full records in batches.
  3. Follow the stored cursor. Changes made while step 2 ran are replayed; because you upsert by id, replaying them is harmless.
Taking the cursor before the copy is what guarantees that nothing is lost between the two.
Feed history starts at feed_start, when the feed was launched, not at the beginning of each register. Whole-register exports are not part of v1; for very large registers, talk to us before copying them through the API.

The polling loop

Rules the loop follows:
  • Store the cursor after every page, after the page’s records are saved. If you can, store it in the same transaction as the records. A crash then replays at most one page.
  • Upsert by trademark.id. Never append: the same record arrives again whenever it changes, and replays are normal.
  • Poll at most every 15 minutes. Changes are published in batches after each register update, so polling more often rarely finds anything new. A poll that returns no changes is not billed, but it still counts toward your per-minute rate limit.
  • Keep the scope fixed. Send the same jurisdiction on every call, and never send since together with cursor.

Starting from a time

Instead of subscribing from now, you can start from a past time with since, an RFC 3339 timestamp with Z or an offset:
since is inclusive, because several changes can share one timestamp. It cannot be earlier than feed_start; an earlier value gets 400. Use since on the first call only, then follow the cursor.

Recovering a lost cursor

If your stored cursor is lost, or rejected with 400 invalid-cursor, restart with since set to the created_at of the last item you processed. Items with that exact timestamp are delivered again; your upserts absorb them.

Reloads, bursts and removals

  • A register that is reloading is skipped and listed in unavailable_jurisdictions; its changes follow when the reload ends. If every register in your scope is reloading, the call gets 503 jurisdiction-unavailable with Retry-After of at least 900 seconds. Your cursor stays valid.
  • Reloads and processing changes republish many records at once. Compare the fields you care about before you raise alerts. See How records change.
  • Records removed by an office are not announced in v1. Re-check the records you depend on with batch retrieve from time to time and handle not_found.

Feed or polling by id?

The feed’s cost grows with how much your registers change, not with how many records you care about. If you track a few thousand marks spread over busy registers, polling those ids with batch retrieve can be cheaper: 5,000 marks checked daily cost 50 calls a day. Docketing sync compares both approaches.