Skip to main content
Signa provides a dedicated sandbox environment so you can develop and test your integration without touching live data or consuming production rate limits.

Sandbox Environment

Test API Keys

Test keys use the sig_test_ prefix and are created from the same dashboard as production keys:
sig_test_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4
Test keys connect to the sandbox environment automatically. No separate base URL is required — the API routes requests based on the key prefix:
# This hits the sandbox because the key is sig_test_
curl -H "Authorization: Bearer sig_test_YOUR_KEY" \
  https://api.signa.so/v1/trademarks/search \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"query": "test"}'
Never use sig_live_ keys in automated tests, CI pipelines, or development environments. Live keys operate on real data and count against your production rate limits.

Sandbox vs. Production

AspectSandbox (sig_test_)Production (sig_live_)
DataFixture dataset (~10,000 trademarks)Live data from production offices
Rate limits100 reads/min, 50 search/min, 20 writes/minPer-plan limits
WebhooksDelivered to your endpoint (test events)Delivered to your endpoint (real events)
ResponsesInclude "livemode": falseInclude "livemode": true
BillingFreePer-plan pricing
Sandbox rate limits are intentionally lower than production. This ensures your integration handles rate limiting correctly during development.

Fixture Data

The sandbox is pre-populated with a stable dataset of ~10,000 trademarks across multiple jurisdictions. This data is realistic but synthetic — it does not correspond to real trademark applications.

Well-Known Fixture IDs

Use these IDs in your tests for predictable results:
IDMark TextJurisdictionStatusNice Classes
tm_test_us_001ACME WIDGETSUSregistered9, 42
tm_test_us_002GLOBEX CORPUSfiled35
tm_test_eu_001AURORA HEALTHEUpublished5, 44
tm_test_eu_002NOVA SYSTEMSEUopposed9, 38
tm_test_wo_001ZENITH BRANDWOregistered25

Fixture Search Terms

These queries return predictable result counts in the sandbox:
QueryModeExpected Results
"acme"text12 marks
"health"text45 marks
"nova"phonetic23 marks (includes NOVA, NOOVA, KNOVA)
"tech"fuzzy89 marks

Fixture Owners and Entities

IDNameType
own_test_001Acme Widgets Inc.Corporation
own_test_002Globex CorporationCorporation
att_test_001Jane SmithAttorney
firm_test_001Smith & Associates LLPLaw firm

Webhook Testing

Sandbox keys generate real webhook deliveries, making it easy to test your webhook handler end-to-end.

Triggering Test Events

Use the webhook test endpoint to send a synthetic event to your registered endpoint:
POST /v1/webhooks/whk_test_abc123/test
{
  "event_type": "trademark.status_changed"
}
This sends a realistic payload to your webhook URL using fixture data. The event’s livemode field is set to false.

Local Development with Tunnels

For local development, use a tunnel service to expose your localhost to the internet:
# Start a tunnel to your local webhook handler
ngrok http 3000

# Register the tunnel URL as your webhook endpoint
curl -X POST https://api.signa.so/v1/webhooks \
  -H "Authorization: Bearer sig_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://abc123.ngrok.io/webhooks/signa",
    "events": ["trademark.status_changed", "deadline.approaching"]
  }'
The webhook test endpoint is useful for verifying signature verification logic. The test payload is signed with your webhook secret, just like production events.

Integration Test Examples

Basic: Verify Authentication

import { describe, it, expect } from 'vitest';

const API_KEY = process.env.SIGNA_TEST_API_KEY!;
const BASE_URL = 'https://api.signa.so/v1';

describe('Signa API Authentication', () => {
  it('should authenticate with a valid test key', async () => {
    const response = await fetch(`${BASE_URL}/offices`, {
      headers: { Authorization: `Bearer ${API_KEY}` },
    });

    expect(response.status).toBe(200);
    const body = await response.json();
    expect(body.object).toBe('list');
  });

  it('should reject an invalid key', async () => {
    const response = await fetch(`${BASE_URL}/offices`, {
      headers: { Authorization: 'Bearer sig_test_invalid_key' },
    });

    expect(response.status).toBe(401);
  });
});

Search and Paginate

import { Signa } from '@signa-so/sdk';
import { describe, it, expect } from 'vitest';

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

describe('Search and pagination', () => {
  it('should search and paginate through results', async () => {
    // First page
    const page1 = await signa.search.query({
      query: 'health',
      limit: 10,
    });

    expect(page1.data.length).toBe(10);
    expect(page1.has_more).toBe(true);
    expect(page1.pagination.cursor).toBeTruthy();

    // Second page
    const page2 = await signa.search.query({
      query: 'health',
      limit: 10,
      cursor: page1.pagination.cursor,
    });

    expect(page2.data.length).toBeGreaterThan(0);

    // Verify no duplicates across pages
    const page1Ids = new Set(page1.data.map((t) => t.id));
    const page2Ids = page2.data.map((t) => t.id);
    for (const id of page2Ids) {
      expect(page1Ids.has(id)).toBe(false);
    }
  });
});

Batch Fetch with Error Handling

import { Signa } from '@signa-so/sdk';
import { describe, it, expect } from 'vitest';

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

describe('Batch operations', () => {
  it('should handle mixed success and not-found in batch', async () => {
    const response = await signa.trademarks.batch({
      ids: ['tm_test_us_001', 'tm_nonexistent_id', 'tm_test_eu_001'],
    });

    // Overall request succeeds
    expect(response.data).toHaveLength(3);

    // First and third items succeed
    expect(response.data[0].status).toBe('success');
    expect(response.data[0].data.mark_text).toBe('ACME WIDGETS');

    // Second item is not found
    expect(response.data[1].status).toBe('error');
    expect(response.data[1].error.type).toBe('not_found');

    // Third item succeeds
    expect(response.data[2].status).toBe('success');
  });
});

CI/CD Integration

Environment Variables

Set these in your CI pipeline:
VariableValueDescription
SIGNA_TEST_API_KEYsig_test_...Sandbox API key for integration tests
SIGNA_WEBHOOK_SECRETwhsec_...Webhook signing secret for signature tests

GitHub Actions Example

name: Integration Tests
on: [push]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - run: npm ci
      - run: npm run test:integration
        env:
          SIGNA_TEST_API_KEY: ${{ secrets.SIGNA_TEST_API_KEY }}
          SIGNA_WEBHOOK_SECRET: ${{ secrets.SIGNA_WEBHOOK_SECRET }}
Store test API keys in your CI provider’s secrets manager. Even though they only access sandbox data, treat them as credentials.

Sandbox Limitations

A few things to keep in mind when testing against the sandbox:
The sandbox dataset is reset to its baseline state every Sunday at 00:00 UTC. Any records you create during testing (portfolios, watches) are removed. Design your tests to set up their own state at the beginning of each run.
Sandbox webhooks follow the same retry policy as production, but delivery is deprioritized during peak load. Do not rely on sub-second delivery latency in your tests.
The sandbox includes fixture trademarks for US, EU, WO, CA, GB, DE, and AU. Other jurisdictions return empty results. If you need fixture data for a specific office, contact support.
Sandbox rate limits (100 reads/min, 50 search/min) are intentionally lower than production. If your tests are rate-limited, add small delays between requests or reduce parallelism.