Adding a Trademark Clearance API to Your Domain Registration Flow

Add a trademark clearance API to your domain registration flow in under an hour. Screen 147M+ trademarks before checkout to reduce UDRP disputes and churn.
10 min read

Domain registrars check whether a name is available on DNS. They don't check whether it conflicts with a registered trademark. That gap costs registrants real money: WIPO handled a record 6,192 UDRP (Uniform Domain-Name Dispute Resolution Policy) complaints in 2023 (the latest year with full data), and complainants win roughly 85-90% of the time. Losing means forfeiting the domain, paying legal fees, and often rebranding entirely.

Roughly 350 million domain registrations are processed annually with virtually zero trademark pre-screening. A trademark clearance API call between domain lookup and checkout can surface that risk before the customer commits. This tutorial shows you how to build that check using the Signa trademark clearance API, from raw search to risk-tiered UI warnings.

Why Domain Registrars Need Trademark Clearance

Most developers assume ICANN's Trademark Clearinghouse (TMCH) handles this. It doesn't. The TMCH only operates during sunrise periods for new generic top-level domains (gTLDs). If someone registers nexacloud.com today, and NEXACLOUD is a registered trademark in Class 9, no system warns them. The TMCH never fires. The registrar processes the order. Six months later, a cease-and-desist arrives.

Registrants face UDRP disputes, domain forfeiture, and forced rebranding. Registrars absorb the support burden: dispute resolution tickets, confused customers, and churn from users who lose their domains. For hosting platforms that bundle domain registration, a trademark dispute can unravel an entire customer relationship.

Adding clearance reduces support tickets and liability exposure. It's also a genuine differentiator: none of the major registrars offer a domain name trademark check today. The check doesn't need to be a legal opinion. It's risk awareness, surfaced at the right moment in the flow.

Consult a trademark attorney for legal guidance specific to your situation. The clearance check described here is an automated screening tool, not a substitute for professional legal review.

How the Trademark Clearance API Works

Architecturally, the trademark check slots between two steps that already exist in every registration flow: domain availability lookup and checkout. The domain lookup confirms the name is available on DNS. The trademark check confirms whether that name (or something phonetically similar) is registered as a trademark. Both complete before the user reaches the payment form.

The Signa trademark search API handles the lookup. A single POST /v1/trademarks request accepts the domain name as a query, runs it against 147M+ trademark records across 200+ offices, and returns scored matches in under 300ms. The key is choosing the right search strategies and filters.

Why phonetic matching matters for domains. Domain names are often spoken aloud, abbreviated, or intentionally misspelled. A domain like nexakloud.com won't match an exact search for the trademark NEXACLOUD, but a phonetic search catches it. For domain clearance, include phonetic and fuzzy strategies alongside exact.

Filtering by Nice class. Nice classes are the international system for categorizing the goods and services a trademark covers. Class 9 (software), Class 42 (SaaS and technology services), and Class 35 (advertising and business services) are the most relevant for domain registrations tied to tech products. Filtering by these classes reduces noise from unrelated marks. A "NEXACLOUD" trademark registered for agricultural equipment (Class 7) is a lower risk than one registered for software.

Here's what the raw API call looks like:

curl -X POST "https://api.signa.so/v1/trademarks" \
  -H "Authorization: Bearer $SIGNA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "NEXACLOUD",
    "strategies": ["exact", "phonetic", "fuzzy"],
    "filters": {
      "nice_classes": [9, 35, 42],
      "status_stage": ["registered", "examining", "published", "opposition_period"]
    },
    "limit": 20
  }'

The response includes fields that drive risk assessment. relevance_score (0-100) measures how closely the result matches the query. match_explanation.strategies_matched tells you which strategies triggered the match (a phonetic match on an active trademark is higher risk than a fuzzy-only match on an expired one). status.stage indicates whether the mark is active, under examination, or abandoned.

Risk tiering. Not every match is equally dangerous. A practical framework:

  • High risk: relevance_score of 85 or above, phonetic or exact match, status is registered or examining, and the Nice class overlaps with the domain's intended use. This combination strongly suggests a conflict.
  • Medium risk: Score between 70 and 85, or the mark is in an adjacent Nice class, or the status is published or opposition_period. Worth flagging but not necessarily blocking.
  • Low risk: Fuzzy-only match, or the mark is abandoned or expired. These appear in results but rarely represent actionable risk.

For a deeper breakdown of clearance search methodology, see the practical guide to trademark clearance searches.

Building the Integration

Step 1: Install the SDK and configure your API key

npm install @signa-so/sdk

const signa = new Signa({ api_key: process.env.SIGNA_API_KEY });

The SDK handles authentication, retries, and response parsing. For a walkthrough of the SDK's full capabilities, see how to automate trademark search with 10 lines of code.

Step 2: Write the clearance check function

This function takes a domain name, strips the TLD, and runs a trademark search with the strategies and filters appropriate for domain clearance.


const signa = new Signa({ api_key: process.env.SIGNA_API_KEY });

interface ClearanceResult {
  id: string;
  markText: string;
  relevanceScore: number;
  strategiesMatched: string[];
  statusStage: string;
  niceClasses: number[];
  owner: string;
}

async function checkTrademarkClearance(domain: string): Promise<ClearanceResult[]> {
  // Strip TLD: "nexacloud.com" -> "NEXACLOUD"
  // For multi-part TLDs (.co.uk, .com.au), use a public suffix
  // library like `psl` instead of this regex.
  const query = domain.replace(/\.[a-z]+$/i, '').toUpperCase();

  const results = await signa.trademarks.search({
    query,
    strategies: ['exact', 'phonetic', 'fuzzy'],
    filters: {
      nice_classes: [9, 35, 42],
      status_stage: ['registered', 'examining', 'published', 'opposition_period'],
    },
  });

  const items = await results.toArray();

  return items.map((tm) => ({
    id: tm.id,
    markText: tm.mark_text,
    relevanceScore: tm.relevance_score,
    strategiesMatched: tm.match_explanation.strategies_matched,
    statusStage: tm.status.stage,
    niceClasses: tm.classifications.map((c) => c.nice_class),
    owner: tm.owners[0]?.name ?? 'Unknown',
  }));
}

The function returns a flat array of structured results. Each result carries enough information to make a risk decision in the next step.

Step 3: Assess risk level

This function categorizes each trademark match into a risk tier based on score, match strategy, and registration status.

type RiskLevel = 'high' | 'medium' | 'low';

interface RiskAssessment {
  level: RiskLevel;
  results: ClearanceResult[];
  summary: string;
}

function assessRisk(results: ClearanceResult[]): RiskAssessment {
  const high = results.filter(
    (r) =>
      r.relevanceScore >= 85 &&
      (r.strategiesMatched.includes('phonetic') || r.strategiesMatched.includes('exact')) &&
      ['registered', 'examining'].includes(r.statusStage)
  );

  const medium = results.filter(
    (r) =>
      !high.includes(r) &&
      (r.relevanceScore >= 70 ||
        ['published', 'opposition_period'].includes(r.statusStage))
  );

  const low = results.filter(
    (r) => !high.includes(r) && !medium.includes(r)
  );

  if (high.length > 0) {
    return {
      level: 'high',
      results: high,
      summary: `Found ${high.length} high-risk trademark conflict${high.length > 1 ? 's' : ''}. ` +
        `Top match: "${high[0].markText}" (score: ${high[0].relevanceScore}, ` +
        `status: ${high[0].statusStage}, owner: ${high[0].owner}).`,
    };
  }

  if (medium.length > 0) {
    return {
      level: 'medium',
      results: medium,
      summary: `Found ${medium.length} potential trademark conflict${medium.length > 1 ? 's' : ''} ` +
        `worth reviewing before proceeding.`,
    };
  }

  return {
    level: 'low',
    results: low,
    summary: low.length > 0
      ? `Found ${low.length} low-relevance match${low.length > 1 ? 'es' : ''} (fuzzy or expired). Minimal risk.`
      : 'No trademark conflicts found for this domain name.',
  };
}

Step 4: Wire into the registration UI

With the clearance check and risk assessment in place, the final step is rendering a warning in the registration flow. The exact UI depends on your frontend framework, but the pattern is the same: call checkTrademarkClearance after the domain lookup resolves, run assessRisk on the results, and conditionally render a banner.

// Pseudocode: registration flow handler
async function onDomainSelected(domain: string) {
  const matches = await checkTrademarkClearance(domain);
  const risk = assessRisk(matches);

  if (risk.level === 'high') {
    showWarningBanner({
      severity: 'error',
      title: 'Trademark conflict detected',
      message: risk.summary,
      action: 'Consider consulting a trademark attorney before registering this domain.',
      allowProceed: true,
    });
  } else if (risk.level === 'medium') {
    showWarningBanner({
      severity: 'warning',
      title: 'Potential trademark conflict',
      message: risk.summary,
      action: 'Review the matches below before proceeding.',
      allowProceed: true,
    });
  }
  // Low risk: no banner, proceed normally
}

The important design decision: warn, don't block. The clearance check is a risk signal, not a legal determination. Users should always be able to proceed. The goal is informed registration, not gatekeeping.

Related tutorials:

Handling Edge Cases

Generic terms and common words

A domain like cloudstore.com will return hundreds of trademark matches because "cloud" and "store" appear in thousands of registrations. The Nice class filter handles most of the noise, but you may need additional filtering for very common terms.

function filterGenericMatches(results: ClearanceResult[]): ClearanceResult[] {
  return results.filter((r) => {
    const hasStrongMatch = r.strategiesMatched.some(
      (s) => s === 'phonetic' || s === 'exact'
    );
    const hasRelevantClass = r.niceClasses.some(
      (c) => [9, 35, 42].includes(c)
    );
    return hasStrongMatch && hasRelevantClass;
  });
}

This filters out fuzzy-only matches on generic terms, which almost always represent noise rather than genuine conflicts.

Internationalized domain names (IDNs)

IDN domains use non-Latin characters (e.g., domains in Chinese, Arabic, or Cyrillic scripts). The Signa API handles Unicode normalization internally, but convert IDN domains from Punycode (the xn-- encoded form) to Unicode before sending the query. Most domain registration systems already store both representations.

Rate limiting and caching

For high-traffic registration flows, caching trademark results makes sense. Trademark data changes slowly compared to DNS records. A 24-hour TTL on cached results is reasonable: new trademark filings take weeks or months to appear in office databases, so a day-old result is effectively current.

Use the domain name (with TLD stripped, uppercased) as the cache key. The Signa API includes rate limit headers in every response, so you can implement backoff without guessing.

Disclaimer language

The warning banner should never imply legal certainty. Effective disclaimer language for the UI:

"This automated screening checks registered trademarks and is provided for informational purposes only. It is not legal advice. Consult a trademark attorney for guidance specific to your situation."

Keep the disclaimer visible but concise. A wall of legal text next to a risk warning undermines both the warning and the disclaimer.

From One-Time Check to Ongoing Monitoring

A clearance check at registration catches conflicts that exist today. It doesn't catch a trademark filed next week. For platforms where customers hold domains for years, one-time screening leaves a gap.

The Signa monitoring API extends the clearance check into an ongoing process. A similarity watch on the term "NEXACLOUD" flags any new filing that matches phonetically or exactly, across specified Nice classes. When a new conflict appears, a webhook notification can trigger an email to the domain holder with the details.

This turns a one-time feature into a retention tool: customers stay because your platform actively protects their domain investment. For implementation details on setting up watches and webhook-driven alerts, see the guide to automating trademark search.

Get Started with the Trademark Clearance API

This tutorial covered the full integration: searching the Signa API for trademark conflicts, tiering results by risk level, and rendering warnings in a domain registration UI. The trademark clearance API adds a single async call to your existing flow and returns in under 300ms.

Sign up for a free Signa API key and add trademark clearance to your registration flow in under an hour.