Svix
Elixir client for the Svix webhook API.
Installation
Add svix to your list of dependencies in mix.exs:
def deps do
[
{:svix, "~> 0.1.0"}
]
endUsage
Client Setup
client = Svix.new("sk_your_token.eu")
The token suffix (.us, .eu, .ca, .au, .in) automatically selects the
regional API endpoint. Override with the :server_url option:
client = Svix.new("sk_token", server_url: "https://self-hosted.example.com")Applications
{:ok, app} = Svix.Application.create(client, %{name: "My App", uid: "my-app-uid"})
{:ok, apps} = Svix.Application.list(client, limit: 10)
{:ok, app} = Svix.Application.get(client, "app_123")
{:ok, _} = Svix.Application.update(client, "app_123", %{name: "Updated"})
{:ok, nil} = Svix.Application.delete(client, "app_123")
{:ok, app} = Svix.Application.get_or_create(client, %{name: "My App", uid: "my-uid"})Messages
{:ok, msg} = Svix.Message.create(client, "app_123", %{
event_type: "invoice.paid",
payload: %{id: "inv_123", amount: 1000}
})
{:ok, messages} = Svix.Message.list(client, "app_123",
event_types: ["invoice.paid"],
limit: 20
)Endpoints
{:ok, ep} = Svix.Endpoint.create(client, "app_123", %{
url: "https://example.com/webhook",
filter_types: ["invoice.paid"]
})
{:ok, secret} = Svix.Endpoint.get_secret(client, "app_123", "ep_123")Event Types
{:ok, _} = Svix.EventType.create(client, %{
name: "invoice.paid",
description: "Invoice was paid"
})Message Attempts
{:ok, attempts} = Svix.MessageAttempt.list_by_endpoint(client, "app_123", "ep_123",
status: 0,
limit: 50
)
{:ok, nil} = Svix.MessageAttempt.resend(client, "app_123", "msg_123", "ep_123")Webhook Verification
Verify incoming webhook signatures:
wh = Svix.Webhook.new("whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw")
case Svix.Webhook.verify(wh, raw_body, headers) do
{:ok, data} ->
# Process the verified webhook payload
handle_event(data)
{:error, _reason} ->
# Reject the request
send_resp(conn, 400, "Invalid signature")
end
Where headers is a map with string keys:
headers = %{
"svix-id" => get_header(conn, "svix-id"),
"svix-timestamp" => get_header(conn, "svix-timestamp"),
"svix-signature" => get_header(conn, "svix-signature")
}Streaming
{:ok, stream} = Svix.Stream.create(client, %{uid: "my-stream"})
{:ok, sink} = Svix.Stream.Sink.create(client, stream["id"], %{type: "http", url: "https://..."})
{:ok, _} = Svix.Stream.Events.create(client, stream["id"], %{
event_type: "order.created",
payload: %{order_id: "ord_123"}
})Ingest
{:ok, source} = Svix.Ingest.Source.create(client, %{name: "GitHub", type: %{type: "generic"}})
{:ok, ep} = Svix.Ingest.Endpoint.create(client, source["id"], %{
url: "https://example.com/ingest"
})Error Handling
All functions return {:ok, result} or {:error, exception} tuples. Bang
variants (create!, get!, etc.) raise on error.
case Svix.Application.get(client, "app_123") do
{:ok, app} ->
app["name"]
{:error, %Svix.Error.ApiError{status: 404}} ->
nil
{:error, %Svix.Error.ValidationError{detail: errors}} ->
Logger.error("Validation failed: #{inspect(errors)}")
endAll Resources
| Module | Description |
|---|---|
Svix.Application | Manage applications |
Svix.Authentication | Portal access and token management |
Svix.Endpoint | Manage endpoints (URLs, headers, secrets, recovery) |
Svix.EventType | Manage event types |
Svix.Message | Send and manage messages |
Svix.MessageAttempt | Query delivery attempts |
Svix.Integration | Manage integrations |
Svix.Webhook | Verify webhook signatures |
Svix.OperationalWebhookEndpoint | Operational webhook endpoints |
Svix.BackgroundTask | Query background tasks |
Svix.Statistics | Usage statistics |
Svix.Environment | Export/import configuration |
Svix.Connector | Manage connectors |
Svix.Stream | Manage event streams |
Svix.Stream.EventType | Stream event types |
Svix.Stream.Events | Stream events |
Svix.Stream.Sink | Stream sinks |
Svix.Ingest.Source | Ingest sources |
Svix.Ingest.Endpoint | Ingest endpoints |
Svix.MessagePoller | Poll for messages |
License
MIT