@prismfy/prismfy
v1.0.0
Published
Official JavaScript/TypeScript SDK for the Prismfy web search API
Maintainers
Readme
Prismfy JavaScript / TypeScript SDK
Official JS/TS client for the Prismfy web search API. Works in Node.js 18+, Bun, Deno, and modern browsers.
Installation
npm install prismfy
# or
yarn add prismfy
# or
pnpm add prismfyQuick start
import { Prismfy } from 'prismfy'
const client = new Prismfy({ apiKey: 'ss_live_...' })
const result = await client.search('best Python libraries 2026')
for (const r of result.results) {
console.log(r.title)
console.log(r.url)
console.log(r.content.slice(0, 200))
console.log()
}Use environment variables (recommended):
export PRISMFY_API_KEY="ss_live_..."const client = new Prismfy() // reads PRISMFY_API_KEY automaticallyFeatures
- ✅ Full TypeScript support — complete type definitions included
- ✅ Zero dependencies — uses native
fetch(Node 18+, browsers, Bun, Deno) - ✅ Works in browsers, Node.js, Bun, Deno, and edge runtimes (Vercel, Cloudflare)
- ✅ ESM + CommonJS — both module formats shipped
- ✅ Typed error hierarchy with specific exception classes
- ✅ Overloaded
search()— accepts string or object
Usage
Search
// Simple string argument
const result = await client.search('TypeScript generics')
// Full options
const result = await client.search('transformer architecture', {
engines: ['arxiv', 'pubmed', 'google'], // Pro/Enterprise
timeRange: 'month',
language: 'en',
page: 1,
})
// Domain-scoped
const result = await client.search('Array.from()', {
domain: 'developer.mozilla.org',
})
// Object-style (alternative)
const result = await client.search({
query: 'rust async programming',
page: 2,
engines: ['google', 'bing'],
})
// Access results
console.log(`${result.results.length} results, cached: ${result.cached}`)
console.log(`Duration: ${result.meta.durationMs}ms`)
console.log(`Engines: ${result.meta.engines.join(', ')}`)User profile & quota
const profile = await client.user.me()
console.log(profile.tier) // 'free' | 'pro' | 'enterprise'
console.log(profile.quota.remaining) // requests left this month
console.log(profile.quota.expiresAt) // reset dateSearch history
const history = await client.user.searches({ limit: 20 })
for (const item of history.searches) {
console.log(item.query, item.status, item.durationMs)
}Usage / billing log
const usage = await client.user.usage({ limit: 50 })
for (const event of usage.history) {
console.log(event.event, event.createdAt)
}API key management
// List all keys
const keys = await client.user.keys()
// Create a new key
const newKey = await client.user.createKey({ name: 'Production' })
console.log(newKey.key) // ss_live_... — save this, shown only once!
// Delete a key (immediately invalidated)
await client.user.deleteKey(newKey.id)Plans & engine catalog
const { plans, allEngines, engines } = await client.plans()
plans.forEach(p => {
console.log(`${p.name}: ${p.limits.rpm} rpm, ${p.limits.requestsMonth} req/mo`)
})
console.log('All engines:', allEngines)
// ['google', 'bing', 'brave', 'yahoo', 'yahoo news', 'hackernews', ...]Health check
const health = await client.health()
console.log(health.status, health.checks)
// { status: 'ok', checks: { db: 'ok', redis: 'ok' } }Error handling
import {
Prismfy,
PrismfyRateLimitError,
PrismfyQuotaError,
PrismfyAuthError,
PrismfyTimeoutError,
PrismfyError,
} from 'prismfy'
const client = new Prismfy()
try {
const result = await client.search('query')
} catch (err) {
if (err instanceof PrismfyRateLimitError) {
console.log(`Rate limited. Retry after ${err.retryAfterSeconds}s`)
await new Promise(r => setTimeout(r, err.retryAfterMs + 100))
} else if (err instanceof PrismfyQuotaError) {
console.log('Monthly quota exhausted. Upgrade your plan.')
} else if (err instanceof PrismfyAuthError) {
console.log('Invalid API key.')
} else if (err instanceof PrismfyTimeoutError) {
console.log('Search timed out. Try again.')
} else if (err instanceof PrismfyError) {
console.log(`API error: ${err.statusCode} ${err.code} — ${err.message}`)
}
}Retry with exponential backoff
async function searchWithRetry(
client: Prismfy,
query: string,
maxRetries = 3,
) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await client.search(query)
} catch (err) {
if (err instanceof PrismfyRateLimitError) {
if (attempt === maxRetries - 1) throw err
await new Promise(r => setTimeout(r, err.retryAfterMs + 100))
} else if (err instanceof PrismfyTimeoutError) {
if (attempt === maxRetries - 1) throw err
await new Promise(r => setTimeout(r, 1000 * 2 ** attempt))
} else {
throw err
}
}
}
}Next.js / React example
// app/api/search/route.ts
import { Prismfy } from 'prismfy'
import { NextResponse } from 'next/server'
const client = new Prismfy() // reads PRISMFY_API_KEY
export async function POST(req: Request) {
const { query } = await req.json()
const result = await client.search(query)
return NextResponse.json(result)
}// components/SearchBox.tsx
'use client'
import { useState } from 'react'
import type { SearchResponse } from 'prismfy'
export function SearchBox() {
const [results, setResults] = useState<SearchResponse | null>(null)
async function handleSearch(query: string) {
const res = await fetch('/api/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query }),
})
setResults(await res.json())
}
return (
<div>
<input onKeyDown={e => e.key === 'Enter' && handleSearch(e.currentTarget.value)} />
{results?.results.map(r => (
<div key={r.url}>
<a href={r.url}>{r.title}</a>
<p>{r.content}</p>
</div>
))}
</div>
)
}Engine reference
| Engine | Category | Free | Pro/Enterprise |
|--------|----------|------|----------------|
| google | Web | ✅ | ✅ |
| bing | Web | ✅ | ✅ |
| brave | Web | — | ✅ |
| yahoo | Web | — | ✅ |
| yahoo news | News | — | ✅ |
| hackernews | News | — | ✅ |
| github | Code | — | ✅ |
| pypi | Code | — | ✅ |
| mdn | Code | — | ✅ |
| arxiv | Academic | — | ✅ |
| pubmed | Academic | — | ✅ |
| huggingface | AI | — | ✅ |
| reddit | Community | — | ✅ |
| wikipedia | Reference | — | ✅ |
| askubuntu | Q&A | — | ✅ |
License
MIT
