anakin-elixir
Official Elixir SDK for Anakin — web scraping, crawling, search, and Wire actions.
Status: alpha (v0.1.x). Public API may change between minor versions until v1.0.
Install
Add to your mix.exs:
def deps do
[{:anakin, "~> 0.1"}]
endThen:
mix deps.getRequires Elixir 1.14+.
Quickstart
{:ok, client} = Anakin.Client.new(api_key: "ak-...") # or set ANAKIN_API_KEY
case Anakin.scrape(client, "https://example.com") do
{:ok, doc} -> IO.puts(doc["markdown"])
{:error, e} -> IO.warn(Exception.message(e))
end
The SDK polls long-running jobs internally — Anakin.scrape/3 and friends block until the job reaches a terminal status, then return {:ok, result}. No job IDs to manage, no polling loops to write.
Function overview
| Function | Endpoint | Sync? |
|---|---|---|
Anakin.scrape(client, url, opts \\ []) | POST /url-scraper → poll | async |
Anakin.map(client, url, opts \\ []) | POST /map → poll | async |
Anakin.crawl(client, url, opts \\ []) | POST /crawl → poll | async |
Anakin.search(client, query, opts \\ []) | POST /search | sync |
Anakin.agentic_search(client, prompt, opts \\ []) | POST /agentic-search → poll | async |
Anakin.wire(client, action_id, params \\ %{}) | POST /holocron/task → poll | async |
Anakin.list_sessions/1, create_session/3, save_session/3, update_session/3, delete_session/2 | /browser-sessions/* | various |
Anakin.Countries.supported/0 | offline (bundled) | sync |
Configuration
{:ok, client} = Anakin.Client.new(
api_key: "ak-...", # or ANAKIN_API_KEY env var
base_url: "https://api.anakin.io/v1",
request_timeout_ms: 60_000, # per-request timeout
max_retries: 4, # on 429 / 5xx / transient
poll_interval_ms: 1_000, # initial polling delay
poll_max_interval_ms: 10_000, # capped backoff
poll_timeout_ms: 300_000, # total poll budget
req_options: [] # extra options forwarded to Req.request/2
)
Or, with Anakin.Client.new!/1 to raise on missing key:
client = Anakin.Client.new!(api_key: System.fetch_env!("ANAKIN_API_KEY"))Errors
Every error returned by the SDK is a struct that implements the Exception behaviour:
case Anakin.scrape(client, "https://example.com") do
{:ok, doc} -> doc
{:error, %Anakin.Error.InsufficientCredits{balance: b, required: r}} ->
IO.puts("out of credits: balance=#{b}, needed=#{r}")
{:error, %Anakin.Error.Authentication{}} ->
IO.puts("invalid API key — get a fresh one at anakin.io/dashboard")
{:error, %Anakin.Error.RateLimit{retry_after: ra}} ->
IO.puts("rate limited; retry after #{ra}s")
{:error, %Anakin.Error.JobFailed{reason: reason}} ->
IO.puts("job failed: #{reason}")
{:error, e} ->
IO.puts("unknown error: #{Exception.message(e)}")
endThe error hierarchy:
| Module | When |
|---|---|
Anakin.Error.Authentication | 401 — invalid or missing API key |
Anakin.Error.InsufficientCredits |
402 — out of credits (:balance, :required) |
Anakin.Error.InvalidRequest | 400 — validation failure |
Anakin.Error.RateLimit |
429 — after retry budget exhausted (:retry_after seconds) |
Anakin.Error.JobFailed |
Polled job came back with status="failed" (:reason) |
Anakin.Error.JobTimeout | Polling budget exhausted before terminal status |
Anakin.Error.Server | 5xx — after retries exhausted |
Anakin.Error.Network | DNS / connect / read-timeout |
Anakin.Error | Base struct; unmatched failures fall back here |
Develop
git clone https://github.com/Anakin-Inc/anakin-elixir
cd anakin-elixir
mix deps.get
mix testRelated packages
@anakin-io/sdk— Node.js / TypeScript SDKanakin-sdk— Python SDKgithub.com/Anakin-Inc/anakin-go— Go SDKio.anakin:anakin-sdk— Java SDKanakin-sdk(rubygems) — Ruby SDKAnakin(NuGet) — .NET SDKanakin-sdk(crates.io) — Rust SDKanakin/sdk(Packagist) — PHP SDK@anakin-io/mcp— Model Context Protocol server for AI agents