Skip to main content
This guide is for high-volume consumers: portfolio management tools, docketing systems, and anything else that regularly needs hundreds or thousands of trademark records rather than a handful. It covers chunked batch retrieval, diffing your own records against the register with /v1/reconcile, pulling large result sets efficiently, and staying under your rate limit while doing all of it concurrently.

Chunked batch retrieval

POST /v1/trademarks/batch resolves up to 100 IDs (or office-native identifiers) in a single request and counts as one call against your rate limit, regardless of how many IDs you send. Matched records come back in data; anything that did not resolve comes back in not_found, there is no per-item success/error status to inspect. When you have more than 100 IDs, split them into chunks and process sequentially or with controlled concurrency:
_nwise is a jq helper for fixed-size batching (def _nwise(n): def n1: if length <= n then . else .[0:n], (.[n:] | n1) end; n1;). Any language’s array-chunking utility works the same way, the API side only cares that each request has 100 IDs or fewer.
See Batch Get Trademarks for request/response field detail, and Resilience Patterns for retrying a batch call that fails at the request level (rate limited or a transient 5xx).

Reconciling your own records

If you already hold trademark data (from a legacy system, a spreadsheet, or another vendor) and want to find where it has drifted from the register, use POST /v1/reconcile instead of fetching full records and diffing client-side. Send the fields you have per record, get a field-by-field match/mismatch back, and nothing is stored server-side.
TypeScript
result is one of match, mismatch, not_found, or ambiguous (the identifier matched more than one register record). Reconcile is capped at 100 items per call just like batch, so the same chunking approach applies to a large book of matters.

Pagination at scale

For anything larger than a single batch call, the ordinary list and search endpoints paginate with a cursor. See Pagination for the full contract (cursor stability, 24-hour expiry, sort requirements). A few things matter specifically at volume:
  • Request limit=100 (the max) instead of the default 20 to cut the number of round trips.
  • Use the SDK’s for await iteration or toArray() instead of a manual cursor loop, SignaList follows has_more/cursor for you.
  • For a long-running export, checkpoint the cursor as you go. Cursors expire after 24 hours; if a run stalls past that window, restart pagination rather than trying to resume a stale cursor.
  • Only pass include_total=true when you actually need a count to display. It costs an extra query and is unnecessary for a pure export.
TypeScript

Rate-limit-aware concurrency

Batch and reconcile calls are cheap per item, but you can still run into your plan’s rate limit if you fire many of them concurrently. Every response carries a RateLimit header shaped remaining=<count>, reset=<seconds> (see Rate Limits for the limits themselves). A simple pattern: cap concurrency with a semaphore, and back off early when remaining gets low instead of waiting for a 429.
TypeScript
If you are on the SDK, its built-in retry logic already handles 429 with Retry-After, see Resilience Patterns. The concurrency guard above is for avoiding the 429 in the first place when you control the fan-out.

What’s next

Resilience Patterns

Retry logic, circuit breakers, and idempotent mutations for fault-tolerant integrations.

Pagination

The full cursor-pagination contract for list and search endpoints.