Wolves of Capitol HillAPI Docs

Getting started

From zero to your first congressional-trades request in a few minutes — with or without an API key.

1. Try it without a key

The API works anonymously at evaluation limits (10 requests/minute, 1,000/month, JSON only), so your first request needs nothing but curl:

curl "https://www.wolfofcapitolhill.com/api/v1/trades?limit=5"
{
  "data": [
    {
      "id": "trd_01j8...",
      "politician": {
        "slug": "jane-doe",
        "name": "Jane Doe",
        "chamber": "senate",
        "party": "D",
        "state": "CA"
      },
      "ticker": "NVDA",
      "assetName": "NVIDIA Corporation",
      "assetType": "stock",
      "side": "buy",
      "amountBucket": "15k_50k",
      "amountRange": { "min": 15001, "max": 50000, "label": "$15,001 – $50,000" },
      "tradeDate": "2026-06-24",
      "disclosedAt": "2026-06-30T14:05:00.000Z",
      "filingUrl": "https://efdsearch.senate.gov/search/view/ptr/...",
      "ownerType": "self",
      "conflictSignal": true,
      "conflictReason": "Serves on the Senate Commerce Committee (technology oversight); traded a semiconductor issuer."
    }
  ],
  "nextCursor": "MjAyNi0wNi0zMFQxNDowNTowMC4wMDBafHRyZF8wMWo4"
}

2. Create an account and mint a key

API keys are included in the Pack and Den plans (see Authentication & tiers for the exact limits).

  1. Sign up at wolfofcapitolhill.com/account.
  2. Subscribe to Pack or Den under Account → Billing.
  3. Mint a key under Account → API keys.

Keys look like wch_ followed by 43 URL-safe characters. The full secret is shown exactly once at creation — only its hash is stored, so it cannot be retrieved again. Store it in a secret manager and rotate by minting a new key and revoking the old one.

3. Make an authenticated request

Send the key as a bearer token (or in an X-Api-Key header — see Authentication):

curl -H "Authorization: Bearer wch_YOUR_KEY" \
  "https://www.wolfofcapitolhill.com/api/v1/trades?ticker=NVDA&limit=25"

The same request from JavaScript:

const BASE_URL = 'https://www.wolfofcapitolhill.com';

const response = await fetch(`${BASE_URL}/api/v1/trades?ticker=NVDA&limit=25`, {
  headers: { Authorization: `Bearer ${process.env.WOCH_API_KEY}` },
});

if (!response.ok) {
  // Errors are always { error, hint? } with the right status code.
  const { error, hint } = await response.json();
  throw new Error(`WoCH API ${response.status}: ${error}${hint ? ` — ${hint}` : ''}`);
}

const { data, nextCursor } = await response.json();
console.log(`${data.length} trades; remaining this minute:`,
  response.headers.get('X-RateLimit-Remaining'));

4. Walk the feed

Every list response includes nextCursor. Pass it back as cursor to get the next page; null means you have reached the end:

async function* allTrades(params = {}) {
  let cursor;
  do {
    const query = new URLSearchParams({ ...params, limit: '100' });
    if (cursor) query.set('cursor', cursor);
    const response = await fetch(`${BASE_URL}/api/v1/trades?${query}`, {
      headers: { Authorization: `Bearer ${process.env.WOCH_API_KEY}` },
    });
    if (!response.ok) throw new Error(`WoCH API ${response.status}`);
    const page = await response.json();
    yield* page.data;
    cursor = page.nextCursor;
  } while (cursor !== null);
}

for await (const trade of allTrades({ chamber: 'senate' })) {
  if (trade.conflictSignal) console.log(trade.politician.name, trade.ticker, trade.conflictReason);
}

For incremental syncs, filter with since (an ISO 8601 instant with offset, e.g. 2026-07-01T00:00:00Z) instead of re-walking history — or skip polling entirely and let webhooks push new trades to you.

Where to go next