WikiRest Docs

JavaScript Examples

Complete JavaScript/TypeScript examples for Node.js and browsers.

Basic usage

Using fetch (browser & Node.js 18+)

const API_KEY = process.env.WIKIREST_API_KEY;
const BASE_URL = "https://api.wikirest.com/v1";

async function search(query, limit = 10) {
  const params = new URLSearchParams({ q: query, limit: String(limit) });

  const response = await fetch(`${BASE_URL}/search?${params}`, {
    headers: { "X-API-Key": API_KEY }
  });

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }

  return response.json();
}

// Example usage
const results = await search("machine learning", 5);
results.hits.forEach(hit => {
  console.log(`📄 ${hit.title}`);
  console.log(`   ${hit.text.slice(0, 150)}...`);
});

Get specific chunk

async function getChunk(chunkId) {
  const response = await fetch(`${BASE_URL}/chunk/${chunkId}`, {
    headers: { "X-API-Key": API_KEY }
  });

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }

  return response.json();
}

const chunk = await getChunk("12345_3");
console.log(`Title: ${chunk.title}`);
console.log(`Section: ${chunk.section}`);
console.log(`Text: ${chunk.text}`);

Get full page

async function getPage(pageId, format = "chunks") {
  const params = new URLSearchParams({ format });

  const response = await fetch(`${BASE_URL}/page/${pageId}?${params}`, {
    headers: { "X-API-Key": API_KEY }
  });

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }

  return response.json();
}

// Get as chunks
const page = await getPage(12345, "chunks");
console.log(`Title: ${page.title}`);
console.log(`Total chunks: ${page.total_chunks}`);

// Get as concatenated text
const pageText = await getPage(12345, "concat");
console.log(`Word count: ${pageText.word_count}`);

TypeScript

// types.ts
export interface SearchHit {
  id: string;
  page_id: number;
  title: string;
  section: string;
  text: string;
  chunk_index: number;
  url: string;
  _formatted?: {
    text: string;
  };
}

export interface SearchResponse {
  hits: SearchHit[];
  query: string;
  processingTimeMs: number;
  estimatedTotalHits: number;
}

export interface Chunk {
  id: string;
  page_id: number;
  title: string;
  section: string;
  text: string;
  chunk_index: number;
  url: string;
  word_count: number;
  modified: string;
}

export interface Page {
  page_id: number;
  title: string;
  url: string;
  extract: string;
  modified: string;
  chunks?: Array<{
    id: string;
    section: string;
    text: string;
    chunk_index: number;
  }>;
  total_chunks?: number;
  text?: string;
  word_count?: number;
}

// client.ts
export class WikiRestClient {
  private apiKey: string;
  private baseUrl: string;

  constructor(apiKey: string, baseUrl = "https://api.wikirest.com/v1") {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
  }

  private async request(endpoint: string, params?: Record): Promise {
    const url = new URL(`${this.baseUrl}${endpoint}`);
    if (params) {
      Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
    }

    const response = await fetch(url.toString(), {
      headers: { "X-API-Key": this.apiKey }
    });

    if (!response.ok) {
      const error = await response.json().catch(() => ({ message: "Unknown error" }));
      throw new Error(`HTTP ${response.status}: ${error.message}`);
    }

    return response.json();
  }

  async search(query: string, options: { limit?: number; offset?: number } = {}): Promise {
    return this.request("/search", {
      q: query,
      limit: String(options.limit ?? 10),
      offset: String(options.offset ?? 0)
    });
  }

  async getChunk(chunkId: string): Promise {
    return this.request(`/chunk/${chunkId}`);
  }

  async getPage(pageId: number, format: "chunks" | "concat" = "chunks"): Promise {
    return this.request(`/page/${pageId}`, { format });
  }
}

// Usage
const client = new WikiRestClient(process.env.WIKIREST_API_KEY!);
const results = await client.search("quantum computing", { limit: 5 });

Node.js with axios

import axios from "axios";

const client = axios.create({
  baseURL: "https://api.wikirest.com/v1",
  headers: { "X-API-Key": process.env.WIKIREST_API_KEY },
  timeout: 30000
});

// Add response interceptor for error handling
client.interceptors.response.use(
  response => response,
  async error => {
    if (error.response?.status === 429) {
      const retryAfter = parseInt(error.response.headers["retry-after"] || "60");
      console.log(`Rate limited. Waiting ${retryAfter}s...`);
      await new Promise(r => setTimeout(r, retryAfter * 1000));
      return client.request(error.config);
    }
    throw error;
  }
);

// Search function
async function search(query, limit = 10) {
  const { data } = await client.get("/search", {
    params: { q: query, limit }
  });
  return data;
}

// Example
const results = await search("neural networks", 5);
console.log(`Found ${results.estimatedTotalHits} results`);

Browser usage

<!DOCTYPE html>
<html>
<head>
  <title>WikiRest Search</title>
</head>
<body>
  <input type="text" id="query" placeholder="Search Wikipedia...">
  <button onclick="search()">Search</button>
  <div id="results"></div>

  <script>
    // Note: Never expose API keys in client-side code for production!
    // Use a backend proxy instead
    const API_KEY = "your_key_here"; // Use backend proxy in production

    async function search() {
      const query = document.getElementById("query").value;
      const resultsDiv = document.getElementById("results");

      try {
        const response = await fetch(
          `https://api.wikirest.com/v1/search?q=${encodeURIComponent(query)}&limit=10`,
          { headers: { "X-API-Key": API_KEY } }
        );

        if (!response.ok) throw new Error(`HTTP ${response.status}`);

        const data = await response.json();

        resultsDiv.innerHTML = data.hits.map(hit => `
          <div class="result">
            <h3><a href="${hit.url}" target="_blank">${hit.title}</a></h3>
            <p>${hit._formatted?.text || hit.text}</p>
          </div>
        `).join("");

      } catch (error) {
        resultsDiv.innerHTML = `<p class="error">Error: ${error.message}</p>`;
      }
    }
  </script>
</body>
</html>

React hook

import { useState, useCallback } from "react";

interface SearchResult {
  id: string;
  title: string;
  text: string;
  url: string;
}

interface UseWikiSearchResult {
  results: SearchResult[];
  loading: boolean;
  error: string | null;
  search: (query: string) => Promise;
}

export function useWikiSearch(apiKey: string): UseWikiSearchResult {
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const search = useCallback(async (query: string) => {
    if (!query.trim()) {
      setResults([]);
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const response = await fetch(
        `https://api.wikirest.com/v1/search?q=${encodeURIComponent(query)}&limit=10`,
        { headers: { "X-API-Key": apiKey } }
      );

      if (!response.ok) {
        throw new Error(`Search failed: ${response.status}`);
      }

      const data = await response.json();
      setResults(data.hits);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Unknown error");
      setResults([]);
    } finally {
      setLoading(false);
    }
  }, [apiKey]);

  return { results, loading, error, search };
}

// Usage in component
function SearchComponent() {
  const { results, loading, error, search } = useWikiSearch("YOUR_API_KEY");
  const [query, setQuery] = useState("");

  return (
    
setQuery(e.target.value)} onKeyPress={e => e.key === "Enter" && search(query)} placeholder="Search Wikipedia..." /> {error &&

{error}

}
); }

Error handling

async function searchWithRetry(query, maxRetries = 3) {
  let lastError;

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(
        `https://api.wikirest.com/v1/search?q=${encodeURIComponent(query)}&limit=10`,
        {
          headers: { "X-API-Key": process.env.WIKIREST_API_KEY },
          signal: AbortSignal.timeout(30000) // 30s timeout
        }
      );

      if (response.ok) {
        return response.json();
      }

      if (response.status === 429) {
        // Rate limited
        const retryAfter = parseInt(response.headers.get("Retry-After") || "60");
        const wait = Math.min(retryAfter, Math.pow(2, attempt) * 1000);
        console.log(`Rate limited. Waiting ${wait}ms...`);
        await new Promise(r => setTimeout(r, wait));
        continue;
      }

      if (response.status >= 500) {
        // Server error - retry
        const wait = Math.pow(2, attempt) * 1000;
        console.log(`Server error. Retrying in ${wait}ms...`);
        await new Promise(r => setTimeout(r, wait));
        continue;
      }

      // Client error - don't retry
      const error = await response.json();
      throw new Error(`${response.status}: ${error.message}`);

    } catch (err) {
      lastError = err;
      if (err.name === "AbortError") {
        console.log("Request timed out. Retrying...");
        continue;
      }
      throw err;
    }
  }

  throw lastError || new Error("Max retries exceeded");
}

Streaming results

// For large result sets, process as they arrive
async function* searchGenerator(query, totalResults = 100) {
  let offset = 0;
  const limit = 50;

  while (offset < totalResults) {
    const response = await fetch(
      `https://api.wikirest.com/v1/search?q=${encodeURIComponent(query)}&limit=${limit}&offset=${offset}`,
      { headers: { "X-API-Key": process.env.WIKIREST_API_KEY } }
    );

    if (!response.ok) throw new Error(`HTTP ${response.status}`);

    const data = await response.json();

    for (const hit of data.hits) {
      yield hit;
    }

    if (data.hits.length < limit) break;
    offset += limit;
  }
}

// Usage
for await (const hit of searchGenerator("artificial intelligence", 100)) {
  console.log(hit.title);
  // Process each result as it arrives
}

Was this page helpful?

Help us improve our documentation