README.md

# taviliy-elixir

Elixir SDK for the [Tavily API](https://tavily.com), modeled after the official Python SDK.

Supported endpoints:
- Search
- Extract
- Crawl
- Map
- Research
- Get research result by `request_id`

Compatibility helpers:
- `get_search_context/3`
- `qna_search/3`
- `get_company_info/3`

## Installation

Add to `mix.exs`:

```elixir
def deps do
  [
    {:taviliy_elixir, "~> 0.1.0"}
  ]
end
```

## Configuration

You can pass an API key directly, or use environment variables.

Supported environment variables:
- `TAVILY_API_KEY`
- `TAVILY_PROJECT`

## Quick start

```elixir
client = Tavily.new!(api_key: "tvly-YOUR_API_KEY")

response = Tavily.Client.search(client, "Who is Leo Messi?")
IO.inspect(response)
```

## Search

```elixir
response =
  Tavily.Client.search(client, "What is Tavily?",
    search_depth: "advanced",
    topic: "news",
    max_results: 5,
    include_answer: "advanced",
    include_raw_content: true,
    include_images: true
  )
```

## Extract

```elixir
response =
  Tavily.Client.extract(client, [
    "https://en.wikipedia.org/wiki/Artificial_intelligence",
    "https://en.wikipedia.org/wiki/Machine_learning"
  ])

IO.inspect(response["results"])
```

## Crawl

```elixir
response =
  Tavily.Client.crawl(client, "https://wikipedia.org/wiki/Lemon",
    max_depth: 3,
    limit: 50,
    instructions: "Find all pages on citrus fruits"
  )
```

## Map

```elixir
response =
  Tavily.Client.map(client, "https://wikipedia.org/wiki/Lemon",
    max_depth: 2,
    limit: 30,
    instructions: "Find pages on citrus fruits"
  )
```

## Research

```elixir
queued =
  Tavily.Client.research(client, "Research the latest developments in AI",
    model: "pro",
    citation_format: "apa"
  )

result = Tavily.Client.get_research(client, queued["request_id"])
IO.inspect(result)
```

Stream mode returns an enumerable of chunks:

```elixir
stream = Tavily.Client.research(client, "Research the latest developments in AI", stream: true)

for chunk <- stream do
  IO.write(chunk)
end
```

## Async client

`Tavily.AsyncClient` mirrors `Tavily.Client`, but each API call returns a `Task`.

```elixir
async_client = Tavily.AsyncClient.new!(api_key: "tvly-YOUR_API_KEY")

task = Tavily.AsyncClient.search(async_client, "What is Tavily?")
response = Tavily.AsyncClient.await(task)
```

## Error handling

The SDK raises typed exceptions for common API responses:
- `Tavily.Errors.BadRequestError` (`400`)
- `Tavily.Errors.InvalidAPIKeyError` (`401`)
- `Tavily.Errors.ForbiddenError` (`403`, `432`, `433`)
- `Tavily.Errors.UsageLimitExceededError` (`429`)
- `Tavily.Errors.TimeoutError` (transport timeout)

## Notes

- `get_search_context/3` and `qna_search/3` are included for parity with the Python SDK, where they are deprecated.
- `close/1` is a no-op compatibility method.