Trademark search, monitoring and portfolio data for n8n, powered by MarkMesh.
Search trademark registers across 30+ offices, and start a workflow the moment a mark you are watching changes — registered, opposed, abandoned, renewed, or a deadline that just moved.
Every record carries provenance: which office it came from, when it was last reconciled, and a citation URL where the office publishes one. That is what makes an automated decision defensible three months later.
- Renewal watch — a filing hits
renewal_reminder, n8n opens a task in your practice-management tool and posts to the team channel. - Opposition alert —
opposition_filedon a client's mark pages the responsible attorney immediately, with the office citation attached. - Clearance triage — a product name arrives from a form, search it across your chosen registers, and route anything with a hit to a human.
- Portfolio sync — mirror filings and their status into your own database or a spreadsheet on a schedule.
Starts a workflow when a watched trademark filing changes.
Activating the workflow registers a webhook endpoint on your MarkMesh organisation; deactivating it removes the endpoint again, so nothing is left behind.
Every delivery is verified before the workflow runs — HMAC-SHA256 over the raw request body, constant-time comparison, and a five-minute timestamp window so a captured request cannot be replayed later. A delivery that fails verification is rejected with a 401 and does not start your workflow.
Subscribe to everything, or pick from: filed, published, registered, renewed, abandoned, expired, opposition_filed, opposition_resolved, owner_changed, agent_changed, address_changed, deadline_created, deadline_missed, deadline_extended, office_action_received, renewal_reminder, renewal_overdue.
MarkMesh only sends events for filings your organisation is watching.
If your trigger never fires, this is almost always why — and it looks exactly like a broken integration. Start a watch first, using the MarkMesh → Watch → Start operation, or the Watches page in MarkMesh.
To separate the two questions, use MarkMesh → Webhook Endpoint → Send Test Event. It sends a delivery down the real path, so it proves the URL, the TLS and your signature check without needing a filing to change. If the test arrives and real events do not, the receiver is fine and the missing piece is a watch.
| Resource | Operations |
|---|---|
| Search | Search registers by mark text, across one or more offices |
| Trademark | Get, Get Many |
| Filing | Get, Get Many |
| Watch | Start, Get Many, Delete |
| Webhook Endpoint | Send Test Event, Get Many |
Search results include a _meta object with the per-office outcome — which offices answered, which failed, which timed out. Check it. A workflow that cannot see that half the offices timed out will treat a partial result set as a complete one.
Settings → Community Nodes → Install, enter n8n-nodes-markmesh, and confirm.
See n8n's community node installation guide for the details, and for the risks n8n asks you to acknowledge when installing any community node.
cd ~/.n8n
npm install n8n-nodes-markmeshRestart n8n afterwards.
Bake it into your image or mount it into ~/.n8n/nodes — see n8n's manual installation guide.
- In MarkMesh, open Developers and create an API key.
- In n8n, add a MarkMesh API credential and paste the key.
The key decides which workspace the connection reaches. There is no organisation ID to look up and no environment to select.
mm_live_*keys act on your live workspacemm_test_*keys act on your sandbox
Sandbox keys do not deliver webhooks. The event is recorded in the MarkMesh delivery ledger as skipped rather than sent, so you can see that it happened — but a trigger on a sandbox key will not fire. Use a live key to test the trigger; the action node works with either.
MarkMesh Trigger (events: opposition_filed)
→ Slack: "Opposition filed against {{ $json.trademark.name }}
at {{ $json.provenance.office }} —
{{ $json.provenance.citation.url }}"
The trigger emits:
{
"id": "evt_…",
"type": "filing.opposition_filed",
"occurred_at": "2026-08-04T09:12:00.000000Z",
"api_version": "2026-08-04",
"event": { "id": "…", "type": "opposition_filed", "description": "…" },
"filing": { "id": "…", "application_number": "…", "status": "…", "office": "…" },
"trademark": { "id": "…", "name": "…" },
"provenance": { "office": "…", "jurisdiction": "…", "served_from": "…",
"fetched_at": "…", "citation": { "url": "…", "kind": "…" } },
"delivery_id": "…"
}Mind provenance.citation.kind:
office_record— the URL resolves to this record. Safe to cite as the source.office_portal— the office publishes no per-record page; the link is its search. Do not present it as a citation of one mark.unavailable— no public URL exists for that office.
Enable Raw Payload in the trigger's options if you would rather handle the envelope yourself.
- n8n 1.x (
n8nNodesApiVersion: 1) - Node.js 20.15 or later, matching n8n's own requirement
The trigger cannot deliver to http://localhost — MarkMesh validates that a destination is publicly reachable and refuses private, loopback and link-local addresses. To develop against a local n8n, use n8n start --tunnel or a deployed instance.
If you consume MarkMesh webhooks elsewhere, the signature is the same shape as Stripe's:
MarkMesh-Signature: t=<unix seconds>,v1=<hex hmac-sha256>
Recompute HMAC-SHA256(secret, "<t>.<raw body>") and compare in constant time. Use the raw body bytes — re-serialising parsed JSON changes key order and whitespace, and the signature will not match. That is the most common mistake with this scheme.
npm install
npm run build # compile TypeScript, copy icons into dist/
npm run lint # n8n's community-node rules
npm run formatTry it against a local n8n:
npm run build
npm link
cd ~/.n8n && npm link n8n-nodes-markmeshIssues and pull requests welcome — GitHub issues.
- MarkMesh — and the API for agents and integrations
- Coverage by office — what MarkMesh holds, per register
- n8n community nodes documentation
- Creating nodes for n8n
n8n is a trademark of n8n GmbH. This is a community node, not published or endorsed by n8n.