# Exa

Web search with separate highlights and native relevance, plus native content, answer, and workflow surfaces.

Canonical: https://searchsdk.dev/docs/providers/exa
Markdown: https://searchsdk.dev/docs/providers/exa.md

<a id="overview"></a>

## Normalized search

> **TypeScript reference**
> The API names, code and policy behavior in this article describe the TypeScript SDK. See [your language guide](https://searchsdk.dev/docs/sdks) for its supported surface and limits.

The normalized adapter uses automatic search and requests highlights. Highlight arrays remain separate from snippets. Native numeric scores are preserved. `requestId` contributes provenance and `costDollars.total` contributes USD usage.

**exa-search.ts · server**

```typescript
import { createSearch } from '@belweave/search-sdk';
import { exa } from '@belweave/search-sdk/exa';

const apiKey = process.env.EXA_API_KEY;
if (!apiKey) throw new Error('EXA_API_KEY is required');

const client = createSearch({ provider: exa({ apiKey }) });
const response = await client.web.search({
  query: 'SQLite write concurrency',
  limit: 5,
});
console.log(response.results, response.attempts);
```

Native extracted text, answer generation, Websets, monitors, and team management have distinct response and credential requirements. They are not implicitly invoked by normalized search. Provider-native streaming data is not a SearchResponse.

1,200 include / 1,200 exclude.

<a id="native-client"></a>

## Provider-native client

**exa-native.ts · server**

```typescript
import { createExaClient } from '@belweave/search-sdk/native-exa';

const apiKey = process.env.EXA_API_KEY;
if (!apiKey) throw new Error('EXA_API_KEY is required');

const client = createExaClient({ apiKey, timeoutMs: 10_000 });
const response = await client.search({ body: { query: 'SQLite write concurrency', type: 'auto', numResults: 5 } });
console.log(response.data, response.metadata);
```

Read provider data from `response.data` and sanitized transport details from `response.metadata`. Native TypeScript response types are not runtime schema validation. Preserve the operation's native response and source identities.

<a id="operations"></a>

## Native operation inventory

Methods available on this native client. Paths are relative to each operation's fixed base; a provider may use more than one origin. Eligible operations retry only when you opt into a client retry policy.

| Method | HTTP / relative path | Response / retry eligibility |
| --- | --- | --- |
| `search` | `POST /search` | json · no automatic retry |
| `searchStream` | `POST /search` | SSE stream · no automatic retry |
| `getContents` | `POST /contents` | json · no automatic retry |
| `answer` | `POST /answer` | json · no automatic retry |
| `answerStream` | `POST /answer` | SSE stream · no automatic retry |
| `findSimilar` | `POST /findSimilar` | json · no automatic retry |
| `createMonitor` | `POST /monitors` | json · no automatic retry |
| `listMonitors` | `GET /monitors` | json · eligible |
| `batchMonitors` | `POST /monitors/batch` | json · no automatic retry |
| `getMonitor` | `GET /monitors/{id}` | json · eligible |
| `updateMonitor` | `PATCH /monitors/{id}` | json · no automatic retry |
| `deleteMonitor` | `DELETE /monitors/{id}` | json · no automatic retry |
| `triggerMonitor` | `POST /monitors/{id}/trigger` | json · no automatic retry |
| `listMonitorRuns` | `GET /monitors/{id}/runs` | json · eligible |
| `getMonitorRun` | `GET /monitors/{id}/runs/{runId}` | json · eligible |
| `createAgentRun` | `POST /agent/runs` | json · no automatic retry |
| `createAgentRunStream` | `POST /agent/runs` | SSE stream · no automatic retry |
| `listAgentRuns` | `GET /agent/runs` | json · eligible |
| `getAgentRun` | `GET /agent/runs/{id}` | json · eligible |
| `deleteAgentRun` | `DELETE /agent/runs/{id}` | json · no automatic retry |
| `cancelAgentRun` | `POST /agent/runs/{id}/cancel` | json · no automatic retry |
| `stopAgentRun` | `POST /agent/runs/{id}/stop` | json · no automatic retry |
| `listAgentRunEvents` | `GET /agent/runs/{id}/events` | json · eligible |
| `listAgentRunEventsStream` | `GET /agent/runs/{id}/events` | SSE stream · no automatic retry |
| `createBatch` | `POST /batches` | json · no automatic retry |
| `listBatches` | `GET /batches` | json · eligible |
| `getBatch` | `GET /batches/{id}` | json · eligible |
| `deleteBatch` | `DELETE /batches/{id}` | json · no automatic retry |
| `cancelBatch` | `POST /batches/{id}/cancel` | json · no automatic retry |
| `getTeamInfo` | `GET /v0/teams/me` | json · eligible |
| `createWebset` | `POST /v0/websets` | json · no automatic retry |
| `listWebsets` | `GET /v0/websets` | json · eligible |
| `getWebset` | `GET /v0/websets/{id}` | json · eligible |
| `updateWebset` | `POST /v0/websets/{id}` | json · no automatic retry |
| `deleteWebset` | `DELETE /v0/websets/{id}` | json · no automatic retry |
| `cancelWebset` | `POST /v0/websets/{id}/cancel` | json · no automatic retry |
| `createWebsetSearch` | `POST /v0/websets/{webset}/searches` | json · no automatic retry |
| `getWebsetSearch` | `GET /v0/websets/{webset}/searches/{id}` | json · eligible |
| `cancelWebsetSearch` | `POST /v0/websets/{webset}/searches/{id}/cancel` | json · no automatic retry |
| `createWebsetEnrichment` | `POST /v0/websets/{webset}/enrichments` | json · no automatic retry |
| `updateWebsetEnrichment` | `PATCH /v0/websets/{webset}/enrichments/{id}` | text · no automatic retry |
| `getWebsetEnrichment` | `GET /v0/websets/{webset}/enrichments/{id}` | json · eligible |
| `deleteWebsetEnrichment` | `DELETE /v0/websets/{webset}/enrichments/{id}` | json · no automatic retry |
| `cancelWebsetEnrichment` | `POST /v0/websets/{webset}/enrichments/{id}/cancel` | json · no automatic retry |
| `getWebsetItem` | `GET /v0/websets/{webset}/items/{id}` | json · eligible |
| `deleteWebsetItem` | `DELETE /v0/websets/{webset}/items/{id}` | json · no automatic retry |
| `listWebsetItems` | `GET /v0/websets/{webset}/items` | json · eligible |
| `previewWebset` | `POST /v0/websets/preview` | json · no automatic retry |
| `createWebsetMonitor` | `POST /v0/monitors` | json · no automatic retry |
| `listWebsetMonitors` | `GET /v0/monitors` | json · eligible |
| `getWebsetMonitor` | `GET /v0/monitors/{id}` | json · eligible |
| `updateWebsetMonitor` | `PATCH /v0/monitors/{id}` | json · no automatic retry |
| `deleteWebsetMonitor` | `DELETE /v0/monitors/{id}` | json · no automatic retry |
| `listWebsetMonitorRuns` | `GET /v0/monitors/{monitor}/runs` | json · eligible |
| `getWebsetMonitorRun` | `GET /v0/monitors/{monitor}/runs/{id}` | json · eligible |
| `createImport` | `POST /v0/imports` | json · no automatic retry |
| `listImports` | `GET /v0/imports` | json · eligible |
| `getImport` | `GET /v0/imports/{id}` | json · eligible |
| `updateImport` | `PATCH /v0/imports/{id}` | json · no automatic retry |
| `deleteImport` | `DELETE /v0/imports/{id}` | json · no automatic retry |
| `createWebhook` | `POST /v0/webhooks` | json · no automatic retry |
| `listWebhooks` | `GET /v0/webhooks` | json · eligible |
| `getWebhook` | `GET /v0/webhooks/{id}` | json · eligible |
| `updateWebhook` | `PATCH /v0/webhooks/{id}` | json · no automatic retry |
| `deleteWebhook` | `DELETE /v0/webhooks/{id}` | json · no automatic retry |
| `listWebhookAttempts` | `GET /v0/webhooks/{id}/attempts` | json · eligible |
| `listEvents` | `GET /v0/events` | json · eligible |
| `getEvent` | `GET /v0/events/{id}` | json · eligible |
| `createApiKey` | `POST /api-keys` | json · no automatic retry |
| `listApiKeys` | `GET /api-keys` | json · eligible |
| `getApiKey` | `GET /api-keys/{id}` | json · eligible |
| `updateApiKey` | `PUT /api-keys/{id}` | json · no automatic retry |
| `deleteApiKey` | `DELETE /api-keys/{id}` | json · no automatic retry |
| `getApiKeyUsage` | `GET /api-keys/{id}/usage` | json · eligible |

<a id="lifecycle"></a>

## Limits and operation lifecycle

- Pass `signal` and per-call `timeoutMs` on native request input when needed.
- Persist a returned job identifier before explicitly reading or polling the same job. Native clients do not automatically poll.
- SSE data is incremental provider event text. Parse and validate terminal or error events according to the provider contract; there is no reconnect or replay.
- Native operations may create, delete, ingest, or incur charges. A successful HTTP response is not proof that a remote job completed.

<a id="sources"></a>

## Official sources

Use the official reference for current schemas, account access, and operation-specific requirements.

- [Search reference](https://exa.ai/docs/reference/search)
- [API documentation index](https://exa.ai/docs/llms.txt)

- [Native request and response reference](https://searchsdk.dev/docs/api/native-transport)
- [All providers](https://searchsdk.dev/docs/providers)
