npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jintel-api

v0.3.0

Published

Jintel — paid intelligence API for financial data and research

Readme

Jintel

Multi-source intelligence API for trading and risk research. Part of YojinHQ -- Jintel is the paid data layer that powers Yojin and any other client that needs unified financial, news, and regulatory intelligence through a single GraphQL endpoint.

Quick Start

git clone https://github.com/YojinHQ/Jintel.git
cd Jintel
pnpm install
cp .env.example .env   # fill in API keys
pnpm dev               # starts on http://localhost:4000

Open http://localhost:4000 for the dashboard with org management, usage tracking, and connector controls. Visit /graphiql for the interactive GraphQL playground or /docs for API documentation.

GraphQL API

Single endpoint: POST /api/graphql

All queries require an Authorization: Bearer <api_key> header.

Search entities

{
  searchEntities(query: "Tesla", type: COMPANY, limit: 5) {
    id name type tickers
  }
}

Look up by ticker (primary Yojin path)

{
  entityByTicker(ticker: "AAPL") {
    name type tickers
    market {
      quote { ticker price open high low previousClose changePercent volume marketCap }
      fundamentals { fiftyTwoWeekHigh fiftyTwoWeekLow sector industry }
    }
    risk { overallScore signals { type severity description } }
    regulatory { sanctions { matchedName score } }
  }
}

Batch quotes (portfolio dashboard)

{
  quotes(tickers: ["AAPL", "MSFT", "GOOGL"]) {
    ticker price open high low previousClose changePercent volume marketCap
  }
}

Crypto quotes (via CoinGecko)

{
  cryptoQuotes(ids: ["BTC", "ETH", "SOL"]) {
    id symbol name price marketCap volume24h changePercent24h high24h low24h
  }
}

Technical indicators

{
  technicals(ticker: "AAPL") {
    rsi macd { macd signal histogram }
    bollingerBands { upper middle lower }
    ema sma atr vwma mfi
  }
}

Sanctions screening

{
  sanctionsScreen(name: "Gazprom") {
    listName matchedName score details
  }
}

Each enrichment field resolves independently and in parallel. Clients pay only for the fields they request.

Authentication

Self-serve signup:

curl -X POST http://localhost:4000/api/v1/signup \
  -H "Content-Type: application/json" \
  -d '{"name": "My Org", "type": "personal"}'

Returns an org record and a raw API key. Use the key as a Bearer token:

Authorization: Bearer <your-api-key>

Yojin integration: Yojin calls /api/v1/signup on behalf of users and stores the key in its vault.

Google OAuth: Users can sign in with their Google account at /login. The flow:

  1. Click "Continue with Google" on the login page
  2. Redirects to Google consent → /auth/callback
  3. Auto-creates an org + API key on first login
  4. Sets a session cookie and redirects to the dashboard

Requires GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_REDIRECT_URI environment variables.

Dashboard

A React SPA served at the root (/) provides org management and monitoring:

| Page | Path | Description | |------|------|-------------| | Welcome | / | Landing page | | Login | /login | Google OAuth sign-in | | Overview | /overview | Org stats, API usage summary | | Usage | /usage | Detailed usage tracking with date range filters | | Keys | /keys | API key management (create, list, revoke) | | Connectors | /connectors | Connector health status, per-org enable/disable | | Playground | /playground | Interactive GraphQL query builder |

Built with React 19, React Router, Vite, and Chart.js for data visualization.

Data Sources

Jintel runs on 11 free data connectors — no API keys required:

| Connector | Category | OpenBB | Provides | Models / Endpoints | |---|---|:---:|---|---| | Yahoo Finance | Market | Yes | Quotes, profiles, fundamentals, OHLC, market cap | EquityQuote, EquityInfo | | CBOE | Market | Yes | Index search (S&P 500, VIX, etc.) | IndexSearch | | Multpl | Market | Yes | S&P 500 P/E, Shiller P/E, dividend yield | SP500Multiples | | CoinGecko | Market | — | Crypto prices, market cap, volume, 24h change | /coins/markets, /search | | OFAC | Regulatory | — | US sanctions screening (SDN list, cached locally) | Treasury.gov CSV + local fuzzy match | | SEC EDGAR | Regulatory | Yes | US public company filings search | EquitySearch | | OECD | Economics | Yes | GDP, CPI, interest rates, leading indicators | GdpReal, GdpNominal, GdpForecast, ConsumerPriceIndex, CountryInterestRates, CompositeLeadingIndicator | | IMF | Economics | Yes | Global CPI, economic indicators, trade data | ConsumerPriceIndex, EconomicIndicators | | ECB | Economics | Yes | European balance of payments | BalanceOfPayments | | Deribit | Derivatives | Yes | Crypto futures curves, options chains | FuturesCurve, OptionsChains | | Technical Analysis | Market | Yes | RSI, MACD, Bollinger Bands, EMA, SMA, ATR, VWMA, MFI | EquityHistorical, CryptoHistorical + trading-signals |

9 of 11 connectors route through OpenBB via @traderalice/opentypebb. The remaining 2 (CoinGecko, OFAC) call upstream APIs directly.

Performance

The API includes several optimizations to minimize upstream calls:

  • Mercurius loaders (N+1 elimination) -- Entity nested fields (market, risk, regulatory) use batched loaders. Querying 10 entities makes 2 upstream calls (not 20)
  • Comma-separated batch calls -- quotes() and Entity market loaders send all tickers in a single upstream call to Yahoo Finance (e.g. "AAPL,MSFT,GOOGL")
  • Per-request enrichment cache -- when Entity.risk and Entity.regulatory both need OFAC data for the same entity, the second call reuses the first's result (zero extra API calls)
  • Cross-request TTL cache -- Yahoo Finance quotes cached 2 min, profiles 1 hour. Repeated queries for the same ticker skip API calls entirely
  • Local OFAC SDN list -- sanctions data downloaded once from Treasury.gov and cached 24 hours in memory. Fuzzy bigram matching runs locally with zero per-query API calls
  • Parallel resolution -- entity(id) queries all connectors in parallel instead of waterfall
  • Query depth limit (7) and list size caps (20) prevent unbounded API usage

Org API (self-serve)

Authenticated with the org's own API key (Authorization: Bearer <key>).

| Method | Route | Description | |----------|--------------------------------|--------------------------------------| | GET | /api/v1/me | Org profile + key count | | GET | /api/v1/usage | Aggregated usage (from/to params)| | GET | /api/v1/keys | List org's API keys | | POST | /api/v1/keys | Create a new API key | | DELETE | /api/v1/keys/:keyId | Revoke an API key | | GET | /api/v1/connectors | List connectors with health status | | PUT | /api/v1/connectors/:name | Enable/disable a connector | | GET | /api/v1/session | Session info from httpOnly cookie |

Admin API

All admin routes require the X-Admin-Secret header matching JINTEL_ADMIN_SECRET.

| Method | Route | Description | |----------|--------------------------------|---------------------------| | GET | /admin/orgs | List all organisations | | POST | /admin/orgs | Create an organisation | | GET | /admin/orgs/:orgId/keys | List API keys for an org | | POST | /admin/orgs/:orgId/keys | Create an API key | | DELETE | /admin/keys/:keyId | Revoke an API key | | GET | /admin/keys/:keyId/usage | Query usage (from/to date params) |

Architecture

Client (Yojin UI, curl, any HTTP client)
  |
  |  POST /api/graphql  +  Authorization: Bearer <key>
  v
Fastify + Mercurius (GraphQL)
  |
  +---> Auth (preExecution hook, API key validation)
  +---> Query depth limit (7)
  +---> Rate limiter (100 req/min)
  |
  v
Resolvers  ---->  Per-request enrichCache (deduplicates connector calls)
  |
  v
Connector Registry (11 free connectors)
  |                    +---> Cross-request TTL cache (quotes 2m, profiles 1h)
  +---> Yahoo Finance   (market)      -- Quotes, profiles, fundamentals
  +---> CBOE            (market)      -- Index search
  +---> Multpl          (market)      -- S&P 500 multiples
  +---> CoinGecko       (market)      -- Crypto prices, market cap, volume
  +---> Technicals      (market)      -- RSI, MACD, BB, EMA, SMA, ATR, VWMA, MFI
  +---> OFAC            (regulatory)  -- SDN list (local CSV, 24h cache)
  +---> SEC EDGAR       (regulatory)  -- Company filings search
  +---> OECD            (economics)   -- GDP, CPI, interest rates
  +---> IMF             (economics)   -- Global economic indicators
  +---> ECB             (economics)   -- Balance of payments
  +---> Deribit         (derivatives) -- Crypto futures & options
  |
  v
Upstream APIs (partial failures return partial results)

Testing

pnpm test        # watch mode
pnpm test:ci     # single run

218 tests across 23 test files:

| File | Coverage | |---|---| | auth/store.test.ts | Org CRUD, API key lifecycle, usage tracking, persistence | | auth/service.test.ts | Token authentication edge cases | | auth/org-connector-config.test.ts | Per-org connector enable/disable, isolation, persistence | | auth/org-routes.test.ts | Org API endpoints: profile, usage, key management, connector toggle | | auth/google-routes.test.ts | Google OAuth redirect, callback, org creation, session cookies | | connectors/registry.test.ts | Lookups, category filtering, search connectors | | connectors/market/alpha-vantage.test.ts | Quote fetching, cross-request TTL cache, error handling | | connectors/regulatory/ofac.test.ts | CSV parsing, bigram similarity, SDN search, caching | | graphql/schema.test.ts | SDL validation, Yojin field compatibility | | graphql/context.test.ts | Context building, auth, debug flag, enrichCache | | integration.test.ts | Auth enforcement, signup flow, admin routes, debug extensions |

Commands

pnpm dev          # Start with tsx watch (development)
pnpm build        # Compile TypeScript + build frontend with Vite
pnpm start        # Run compiled output
pnpm test         # Run tests in watch mode (vitest)
pnpm test:ci      # Run tests once
pnpm typecheck    # Type check without emitting
pnpm ci           # Typecheck + test:ci

Tech Stack

  • Fastify -- HTTP server
  • Mercurius -- GraphQL adapter for Fastify
  • TypeScript -- strict mode, ES modules
  • React -- dashboard SPA (with React Router, Vite, Chart.js)
  • Vitest -- test runner (218 tests)
  • Pino -- structured logging
  • tsx -- development watcher

Adding a Connector

Every data source implements the Connector interface in src/connectors/types.ts:

interface Connector {
  name: string;
  source: string;
  category: 'market' | 'news' | 'regulatory' | 'corporate' | 'search';
  search(query: string, options?: SearchOptions): Promise<SourceResult[]>;
  enrich(entity: EntityRef, options?: EnrichOptions): Promise<any>;
  healthcheck(): Promise<HealthStatus>;
}

Create a module under src/connectors/, implement the interface, then call registerConnector() in src/connectors/registry.ts. The new source is immediately available to the GraphQL resolvers with no changes to core logic.

License

Proprietary. All rights reserved.