The prefix means an ID is self-describing in a log line, and passing a
crt_ ID to a shop
endpoint fails immediately with parameter_invalid rather than returning a confusing 404.
Why not just store the URL
URLs are not identity. Over a few months a storefront can change its handle, a product can be delisted and re-listed under a new native ID, and a channel can migrate its URL structure — all without the underlying entity changing.A Unif ID survives
Renames, handle changes, re-listings and URL migrations. It is assigned once and never
recycled.
A URL does not
It is a lookup key that happens to work today. Storing it means re-resolving forever, and
paying for it every time.
Resolving what you already have
POST /v1/resolve accepts up to 100
inputs and takes any of three identifier forms.
url— the most reliable form. Channel and market are inferred from it.handle— needsmarket, because the same handle can exist in several markets.external_id— the channel’s native ID. Needschannelto be unambiguous.
ref is yours. Unif echoes it back untouched, which turns joining results onto your own rows
into a dictionary lookup instead of positional bookkeeping.
Four possible outcomes
Results come back in the order you sent them, and one input failing never fails the batch.resolved
resolved
Exactly one match.
id is set and safe to store.not_found
not_found
No match. Usually a dead listing, a typo, or an entity in a market your workspace has not
enabled. Retrying will not help; the input needs fixing.
ambiguous
ambiguous
More than one match — most often the same product under multiple shops.
candidates lists
them so you can disambiguate with a rule of your own, or surface the choice to a person.unsupported
unsupported
The channel or entity type is not enabled for your workspace. Check
GET /channels; this is an entitlement
problem, not a data problem.Resolve, or enrich
POST /v1/enrich takes exactly the same input
shape and returns the full record instead of just the ID.
Enriching costs more than resolving, so for a one-time backfill of 50,000 rows, resolve first and
then pull metrics only for the rows you keep.
Idempotent by design
Resolving the same identifier twice returns the same ID. There is no create-or-get race, and no deduplication step needed on your side. The one thing to handle isambiguous — the same input
stays ambiguous until you pick a candidate, so record the decision on your row rather than
re-resolving and hoping.