{"openapi":"3.1.0","info":{"title":"Pinakel Trademark Data API","description":"Jurisdiction-scoped trademark lookup for docketing integrators.","version":"1.0.0-pilot"},"paths":{"/v1/usage":{"get":{"summary":"My Usage","description":"Current month's usage for the presented key — so an integrator can\nwatch their own quota without asking us.","operationId":"my_usage_v1_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/health":{"get":{"summary":"Health","operationId":"health_v1_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/{code}/trademarks":{"get":{"summary":"Find Trademarks","description":"Look up trademarks by office number. Exactly one of application_number\nor registration_number is required. Returns a LIST: several offices reuse\nnumbers across series and re-filings, so number → record is not 1:1.","operationId":"find_trademarks_v1__code__trademarks_get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}},{"name":"application_number","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Application Number"}},{"name":"registration_number","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Registration Number"}},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^payload$"},{"type":"null"}],"title":"Expand"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TrademarkDetail"},"title":"Response Find Trademarks V1  Code  Trademarks Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/{code}/trademarks/{uid}":{"get":{"summary":"By Uid","description":"Primary-key fetch: (code, uid) is the stable identity across updates.","operationId":"by_uid_v1__code__trademarks__uid__get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}},{"name":"uid","in":"path","required":true,"schema":{"type":"string","title":"Uid"}},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^payload$"},{"type":"null"}],"title":"Expand"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrademarkDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/{code}/changes":{"get":{"summary":"Changes Since","description":"Forward sync for docketing, keyset-paginated by (loaded_at, uid).\n\nConsumer contract:\n  - The cursor is a DURABLE frontier: store it, resume from it in a later\n    session, and you will see every subsequent version exactly once.\n  - Upsert by (code, uid). A reload on our side re-delivers rows with a\n    new loaded_at — that is correct behaviour, not duplication.\n  - The feed intentionally stops 5 minutes short of now(): loaded_at is a\n    transaction timestamp, so an in-flight load may still commit rows\n    \"in the past\". next_cursor=null therefore means \"caught up to the\n    safety horizon\", not \"nothing will ever follow\".\n  - record_update_date in each item is the office's own freshness stamp;\n    filter on it client-side if you only care about office-side changes.","operationId":"changes_since_v1__code__changes_get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}},{"name":"since","in":"query","required":true,"schema":{"type":"string","format":"date-time","description":"Return records ingested at/after this instant (date or ISO timestamp)","title":"Since"},"description":"Return records ingested at/after this instant (date or ISO timestamp)"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Durable frontier cursor from a previous page/session","title":"Cursor"},"description":"Durable frontier cursor from a previous page/session"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"default":500,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangesPage"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ChangesPage":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TrademarkSummary"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Durable frontier cursor: safe to persist and resume from in a later session. null = caught up."}},"type":"object","required":["items"],"title":"ChangesPage"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"TrademarkDetail":{"properties":{"code":{"type":"string","title":"Code","description":"Jurisdiction code, e.g. CA"},"uid":{"type":"string","title":"Uid","description":"Stable Pinakel identifier, opaque text; unique within code"},"application_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Application Number"},"registration_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Registration Number"},"mark_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mark Name"},"status":{"type":"string","title":"Status","description":"Normalized: Registered/Pending/Abandoned/Cancelled/Unknown"},"tm5_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tm5 Status","description":"TM5 status string where the office provides one"},"kind_of_mark":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind Of Mark"},"mark_feature":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mark Feature"},"application_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Application Date"},"registration_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Registration Date"},"expiry_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Expiry Date"},"record_update_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Record Update Date","description":"Office-side record freshness (attribute only; /changes keys on loaded_at)"},"nice_classes":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Nice Classes"},"loaded_at":{"type":"string","format":"date-time","title":"Loaded At","description":"When Pinakel ingested this version; the /changes sync key"},"payload":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Payload","description":"Full normalized document (expand=payload)"}},"type":"object","required":["code","uid","status","loaded_at"],"title":"TrademarkDetail"},"TrademarkSummary":{"properties":{"code":{"type":"string","title":"Code","description":"Jurisdiction code, e.g. CA"},"uid":{"type":"string","title":"Uid","description":"Stable Pinakel identifier, opaque text; unique within code"},"application_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Application Number"},"registration_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Registration Number"},"mark_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mark Name"},"status":{"type":"string","title":"Status","description":"Normalized: Registered/Pending/Abandoned/Cancelled/Unknown"},"tm5_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tm5 Status","description":"TM5 status string where the office provides one"},"kind_of_mark":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind Of Mark"},"mark_feature":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mark Feature"},"application_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Application Date"},"registration_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Registration Date"},"expiry_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Expiry Date"},"record_update_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Record Update Date","description":"Office-side record freshness (attribute only; /changes keys on loaded_at)"},"nice_classes":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Nice Classes"},"loaded_at":{"type":"string","format":"date-time","title":"Loaded At","description":"When Pinakel ingested this version; the /changes sync key"}},"type":"object","required":["code","uid","status","loaded_at"],"title":"TrademarkSummary","description":"The projection: what a docketing system filters and displays.\n\nOptional fields are genuinely absent in the source for a meaningful share\nof records (pending marks have no registration data; ~36% lack an expiry\ndate). Absence means \"the office did not state it\", never zero-values."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}