XDK Elixir

Hex.pmCI

Auto-generated Elixir client for the X (Twitter) API v2.

Note: This SDK is auto-generated by a fork of XDK, a Rust-based OpenAPI code generator maintained by X's developer platform team. The Elixir target is an addition to that fork. Do not hand-edit files under lib/ or test/ — all changes should be made in the generator templates and re-generated.

Installation

Add xdk_elixir to your list of dependencies in mix.exs:

def deps do
  [
    {:xdk_elixir, "~> 1.0"}
  ]
end

Prerequisites

You need an X Developer account and API credentials. Go to the X Developer Portal to create a project and app.

Depending on the endpoints you want to use, you'll need one or more of:

Credential Env Variable Used For
Bearer TokenBEARER_TOKEN App-only access (read-only public data: search, user lookup, etc.)
Consumer Key + SecretCONSUMER_KEY, SECRET_KEY Generating bearer tokens, OAuth 1.0a signing
Access Token + SecretACCESS_TOKEN, ACCESS_TOKEN_SECRET User-context access via OAuth 1.0a (post, like, follow, DMs, etc.)

Most read endpoints work with just a Bearer Token. Write endpoints (posting, liking, following) require OAuth 1.0a user-context auth.

Usage

1. Start a Finch pool

XDK uses Finch for HTTP. Add it to your supervision tree:

children = [
  {Finch, name: MyApp.Finch}
]

Supervisor.start_link(children, strategy: :one_for_one)

2. Create a client

# App-only (Bearer Token)
client = Xdk.new(finch: MyApp.Finch, bearer: "YOUR_BEARER_TOKEN")

# Or pass auth explicitly
client = Xdk.new(finch: MyApp.Finch, auth: {:bearer, "YOUR_BEARER_TOKEN"})

3. Make API calls

# Look up a user
{:ok, user} = Xdk.Users.get_by_username(client, "elaborapp",
  user_fields: ["id", "name", "public_metrics"]
)

# Search recent posts
{:ok, results} = Xdk.Posts.search_recent(client,
  query: "elixir lang",
  max_results: 10,
  tweet_fields: ["id", "text", "created_at", "author_id"]
)

# Get a post by ID
{:ok, post} = Xdk.Posts.get_by_id(client, "1234567890",
  tweet_fields: ["id", "text", "author_id"]
)

OAuth 1.0a (User Context)

For endpoints that require user-context authentication (posting, liking, following, DMs):

credentials = OAuther.credentials(
  consumer_key: System.get_env("CONSUMER_KEY"),
  consumer_secret: System.get_env("SECRET_KEY"),
  token: System.get_env("ACCESS_TOKEN"),
  token_secret: System.get_env("ACCESS_TOKEN_SECRET")
)

client = Xdk.new(finch: MyApp.Finch, auth: {:oauth1, credentials})

# Post a tweet
{:ok, result} = Xdk.Posts.create(client, %{"text" => "Hello from XDK Elixir!"})

# Like a post
{:ok, _} = Xdk.Users.like_post(client, user_id, %{"tweet_id" => "1234567890"})

Pagination

Use Xdk.Paginator to lazily page through results:

fetch = fn token ->
  opts = [query: "elixir", max_results: 100]
  opts = if token, do: Keyword.put(opts, :pagination_token, token), else: opts
  Xdk.Posts.search_recent(client, opts)
end

# Get all items across pages as a lazy stream
Xdk.Paginator.items(fetch)
|> Enum.take(500)

Streaming

For streaming endpoints (filtered stream, sample stream):

Xdk.Stream.get_filtered_stream(client)
|> Stream.each(fn
  {:ok, tweet} -> IO.inspect(tweet)
  {:error, err} -> IO.warn("Stream error: #{inspect(err)}")
end)
|> Stream.run()

Available Modules

Every X API endpoint group has a corresponding module:

Module Description
Xdk.Users User lookup, followers, following, muting, blocking, bookmarks
Xdk.Posts Tweet CRUD, search, counts, quotes, reposts, analytics
Xdk.Lists List management, members, followers
Xdk.Spaces Twitter Spaces
Xdk.Communities Communities
Xdk.CommunityNotes Community Notes
Xdk.DirectMessages DM conversations and messages
Xdk.Media Media upload
Xdk.Compliance Compliance streams and jobs
Xdk.Stream Filtered and sample streams
Xdk.Trends Trending topics
Xdk.Usage API usage metrics
Xdk.Connections User connections
Xdk.Activity Activity feed
Xdk.AccountActivity Account Activity API
Xdk.Webhooks Webhook management
Xdk.News News
Xdk.Marketplace Marketplace
Xdk.Chat Chat

Error Handling

All API calls return {:ok, map()} or {:error, error}. Errors are structured using Splode:

case Xdk.Users.get_by_username(client, "nonexistent_user_12345") do
  {:ok, data} ->
    IO.inspect(data)

  {:error, %Xdk.Errors.RateLimitError{retry_after_ms: ms}} ->
    Process.sleep(ms)
    # retry...

  {:error, %Xdk.Errors.ApiError{status: 404}} ->
    IO.puts("User not found")

  {:error, %Xdk.Errors.TransportError{reason: reason}} ->
    IO.puts("Network error: #{inspect(reason)}")
end

Configuration

Set defaults via application config so you don't have to pass them every time:

# config/config.exs
config :xdk, :default_config,
  finch: MyApp.Finch

Then just pass auth when creating a client:

client = Xdk.new(bearer: "YOUR_BEARER_TOKEN")

Code Generation

This package is auto-generated from the X API's OpenAPI specification. The generator lives at mikehostetler/xdk (a fork of xdevplatform/xdk).

To regenerate:

cd xdk && cargo run -- elixir --latest true
cp -r xdk/elixir/lib xdk/elixir/test xdk/elixir/mix.exs ../xdk-elixir/
cd ../xdk-elixir && mix deps.get && mix test

License

Apache-2.0 — see LICENSE for details.