Skip to content

Exa Integration

Official Exa API Documentation

Exa is an AI-powered search engine. Use KeyPool to call Exa with your team token and a stable base URL.

KeyPool Endpoint for Exa

To interact with Exa via KeyPool, you will use the following base URL:

{YOUR_KEYPOOL_BASE_URL}/v1/exa

Authentication

Use your KeyPool team token as a bearer token when making requests to the KeyPool Exa endpoint.

Do not send a personal Exa API key when using KeyPool.

Key Features and Usage

KeyPool supports the main Exa SDK workflows, including searching the web, extracting content, finding similar pages, and managing research tasks.

Perform a web search using natural language queries.

Python Example:

from exa_py import Exa
import os

# Replace with your KeyPool base URL and Team Token
KEYPOOL_BASE_URL = os.environ.get("KEYPOOL_BASE_URL")
KEYPOOL_TOKEN = os.environ.get("KEYPOOL_TOKEN")

client = Exa(
    api_key=KEYPOOL_TOKEN,
    base_url=f"{KEYPOOL_BASE_URL}/v1/exa",
)

results = client.search("latest AI research papers", num_results=3)

for result in results.results:
    print(f"URL: {result.url}, Title: {result.title}")

TypeScript Example:

import Exa from "exa-js";

// Replace with your KeyPool base URL and Team Token
const KEYPOOL_BASE_URL = process.env.KEYPOOL_BASE_URL;
const KEYPOOL_TOKEN = process.env.KEYPOOL_TOKEN;

const client = new Exa(KEYPOOL_TOKEN, `${KEYPOOL_BASE_URL}/v1/exa`);

async function searchBasic() {
  const results = await client.search("latest AI research papers", {
    numResults: 3,
  });

  results.results.forEach((result) => {
    console.log(`URL: ${result.url}, Title: ${result.title}`);
  });
}

searchBasic();

2. Search and Contents

Perform a search and directly retrieve the contents of the results.

Python Example:

from exa_py import Exa
import os

KEYPOOL_BASE_URL = os.environ.get("KEYPOOL_BASE_URL")
KEYPOOL_TOKEN = os.environ.get("KEYPOOL_TOKEN")

client = Exa(
    api_key=KEYPOOL_TOKEN,
    base_url=f"{KEYPOOL_BASE_URL}/v1/exa",
)

results = client.search_and_contents(
    "Python asyncio tutorial",
    num_results=1,
    text=True,
)

if results.results:
    print(f"Content from {results.results[0].url}:\n{results.results[0].text[:500]}...") # print first 500 chars

TypeScript Example:

import Exa from "exa-js";

const KEYPOOL_BASE_URL = process.env.KEYPOOL_BASE_URL;
const KEYPOOL_TOKEN = process.env.KEYPOOL_TOKEN;

const client = new Exa(KEYPOOL_TOKEN, `${KEYPOOL_BASE_URL}/v1/exa`);

async function searchAndContents() {
  const results = await client.searchAndContents(
    "Python asyncio tutorial",
    { numResults: 1, text: true }
  );

  if (results.results.length > 0) {
    console.log(`Content from ${results.results[0].url}:\n${results.results[0].text?.substring(0, 500)}...`);
  }
}

searchAndContents();

3. Find Similar

Find web pages similar to a given URL.

Python Example:

from exa_py import Exa
import os

KEYPOOL_BASE_URL = os.environ.get("KEYPOOL_BASE_URL")
KEYPOOL_TOKEN = os.environ.get("KEYPOOL_TOKEN")

client = Exa(
    api_key=KEYPOOL_TOKEN,
    base_url=f"{KEYPOOL_BASE_URL}/v1/exa",
)

results = client.find_similar("https://github.com", num_results=3)

for result in results.results:
    print(f"Similar URL: {result.url}, Title: {result.title}")

TypeScript Example:

import Exa from "exa-js";

const KEYPOOL_BASE_URL = process.env.KEYPOOL_BASE_URL;
const KEYPOOL_TOKEN = process.env.KEYPOOL_TOKEN;

const client = new Exa(KEYPOOL_TOKEN, `${KEYPOOL_BASE_URL}/v1/exa`);

async function findSimilar() {
  const results = await client.findSimilar("https://github.com", {
    numResults: 3,
  });

  results.results.forEach((result) => {
    console.log(`Similar URL: ${result.url}, Title: ${result.title}`);
  });
}

findSimilar();

4. Research Session Affinity

For multi-step operations like Exa research tasks (research.create, research.poll_until_finished), keep the returned research ID and continue polling through the same KeyPool base URL and team token.

Python Example:

from exa_py import Exa
import os
import time

KEYPOOL_BASE_URL = os.environ.get("KEYPOOL_BASE_URL")
KEYPOOL_TOKEN = os.environ.get("KEYPOOL_TOKEN")

client = Exa(
    api_key=KEYPOOL_TOKEN,
    base_url=f"{KEYPOOL_BASE_URL}/v1/exa",
)

# 1. Create a research task
research_task = client.research.create(
    instructions="In one sentence, what is the capital of France?",
    model="exa-research-fast",
)
print(f"Created research task with ID: {research_task.research_id}")

# 2. Poll until the task is finished (KeyPool maintains session affinity)
result = client.research.poll_until_finished(
    research_task.research_id,
    poll_interval=3000, # Poll every 3 seconds
    timeout_ms=120000,  # Timeout after 2 minutes
)

print(f"Research task status: {result.status}")
if result.status == "completed":
    print(f"Research result: {result.results}")

TypeScript Example:

import Exa from "exa-js";

const KEYPOOL_BASE_URL = process.env.KEYPOOL_BASE_URL;
const KEYPOOL_TOKEN = process.env.KEYPOOL_TOKEN;

const client = new Exa(KEYPOOL_TOKEN, `${KEYPOOL_BASE_URL}/v1/exa`);

async function researchSessionAffinity() {
  // 1. Create a research task
  const task = await client.research.create({
    instructions: "In one sentence, what is the capital of France?",
    model: "exa-research-fast",
  });
  console.log(`Created research task with ID: ${task.researchId}`);

  // 2. Poll until the task is finished (KeyPool maintains session affinity)
  const result = await client.research.pollUntilFinished(task.researchId, {
    pollInterval: 3000, // Poll every 3 seconds
    timeoutMs: 120000,  // Timeout after 2 minutes
  });

  console.log(`Research task status: ${result.status}`);
  if (result.status === "completed") {
    console.log(`Research result: ${result.results}`);
  }
}

researchSessionAffinity();

Error Handling

KeyPool handles various error conditions gracefully, providing informative responses. Common error scenarios include:

  • 401 Unauthorized: Invalid or missing KeyPool Team Token.
  • 403 Forbidden: Your Team Token does not have permission to access the Exa service.
  • 429 Quota Exceeded: Your team's rate limit for Exa has been reached.
  • 503 No Available Keys: Exa is temporarily unavailable through your KeyPool workspace.
  • 502 Upstream Failed: The request to the Exa API failed (e.g., network error, Exa API down).

For more details on error structures, refer to the API Reference.


Interactive API Reference

For all Exa endpoints and in-browser testing, see API Reference → Exa.