Skip to content

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/v1 is the major-version stability contract. We will not change a path, status code, or response shape inside /api/v1 once a page in this reference has status: stable.
  • A breaking change ships under a new prefix (/api/v2), and /api/v1 continues to serve in parallel for at least 12 months.
  • Additive changes (new endpoints, new optional response fields) ship inside /api/v1 without 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, alert state, …) are lowercase string literals.
  • null and missing fields are equivalent in responses; clients must accept both.
  • The Content-Type: application/json header is required on every request that has a body.

Example request

Terminal window
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:

ParameterTypeDefaultMaxNotes
limitinteger50200Number of items per page.
cursorstringOpaque cursor returned in the previous response’s pagination.nextCursor.

The response envelope is:

{
"data": [
/* array of resources */
],
"pagination": {
"nextCursor": "ckxyz0000000abcdef",
"limit": 50
}
}
  • nextCursor is null on 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.