Overview
The Trademark Sentinel REST API lets Team and Enterprise customers query watches and alerts, plus rotate API keys, programmatically. It is the same data surface the in-app dashboard uses, exposed as a versioned HTTPS interface.
Base URL and versioning
https://api.trademarksentinel.app/api/v1- The path prefix
/api/v1is the major-version stability contract. We will not change a path, status code, or response shape inside/api/v1once a page in this reference hasstatus: stable. - A breaking change ships under a new prefix (
/api/v2), and/api/v1continues to serve in parallel for at least 12 months. - Additive changes (new endpoints, new optional response fields) ship inside
/api/v1without a version bump. Clients must therefore tolerate unknown JSON fields.
Tier gating
The REST API is Team and Enterprise only. Free and Solo accounts can use the in-app dashboard but cannot create API keys or call /api/v1. See the plan tiers page for the full capability matrix.
A request from a key whose owning user has been downgraded below Team returns 403 forbidden with error.code = "forbidden".
JSON conventions
- Request and response bodies are JSON encoded as UTF-8.
- Field names are
camelCase, matching the underlying Prisma schema. (Plan §3 — the storage and the API speak the same dialect to avoid translation glue.) - Timestamps are ISO-8601 strings in UTC, e.g.
"2026-05-02T11:00:00.000Z". - Identifiers are opaque strings (Prisma
cuid()). Do not parse or order them. - Enums (
watchType,sourceCode,scanCadence, alertstate, …) are lowercase string literals. nulland missing fields are equivalent in responses; clients must accept both.- The
Content-Type: application/jsonheader is required on every request that has a body.
Example request
curl -sS https://api.trademarksentinel.app/api/v1/watches \ -H "Authorization: Bearer ts_REPLACE_ME" \ -H "Content-Type: application/json"Example response
{ "data": [ { "id": "ckxyz0000000abcdef", "watchType": "trademark", "name": "Acme", "attributes": { "niceClasses": [25], "designations": ["US"] }, "sources": ["global_trademark_database"], "scanCadence": "daily", "active": true, "createdAt": "2026-04-30T08:14:01.000Z" } ], "pagination": { "nextCursor": null, "limit": 50 }}Pagination
List endpoints (GET /watches, GET /alerts) return cursor-paginated results. Two query parameters control the page:
| Parameter | Type | Default | Max | Notes |
|---|---|---|---|---|
limit | integer | 50 | 200 | Number of items per page. |
cursor | string | — | — | Opaque cursor returned in the previous response’s pagination.nextCursor. |
The response envelope is:
{ "data": [ /* array of resources */ ], "pagination": { "nextCursor": "ckxyz0000000abcdef", "limit": 50 }}nextCursorisnullon the last page.- Cursors are opaque; clients must round-trip them verbatim and not parse them.
- Total counts are not returned. Drive UIs from “is there a next page” rather than from a count.
Error envelope
All non-2xx responses return a uniform envelope:
{ "error": { "code": "validation_error", "message": "Invalid watch payload.", "details": { "fieldErrors": { "scanCadence": ["Invalid enum value."] } } }}The full code list lives on the errors page.
Rate limits
Each API key has a per-minute steady-state quota; the server returns 429 rate_limited with a Retry-After header when exceeded. See rate limits for the per-tier table and the response headers your client should track.
Authentication
Every request must carry a Bearer API key. See authentication and API key management.