Elixir SDK
Install and authenticate
Add to your mix.exs:
defp deps do
[
{:surge_api, "~> 0.2.0"}
]
endmix deps.getSet your API key in config:
# config/runtime.exs
config :surge_api, api_key: System.get_env("SURGE_API_KEY")Or create a client directly:
client = Surge.Client.new("sk_live_your_key_here")Your first request
Using the default client (reads from application config):
{:ok, message} = Surge.Messages.create(
"acct_01jrzhe8d9enptypyx360pcmxj",
%{to: "+18015551234", body: "Your appointment is confirmed for Friday at 2pm."}
)
IO.puts(message.id) # "msg_01j..."
IO.puts(message.status) # "queued"Or with an explicit client:
client = Surge.Client.new("sk_live_your_key_here")
{:ok, message} = Surge.Messages.create(
client,
"acct_01jrzhe8d9enptypyx360pcmxj",
%{to: "+18015551234", body: "Your appointment is confirmed for Friday at 2pm."}
)Retrieving a message
{:ok, message} = Surge.Messages.get("msg_01kqbhwra9egg8sdcsp9veg391")
IO.inspect(message.body)Error handling
The SDK returns tagged tuples:
case Surge.Messages.create("acct_01j...", %{to: "+18015551234", body: "Hello"}) do
{:ok, message} ->
IO.inspect(message.id)
{:error, %Surge.Error{type: "opted_out", message: msg}} ->
Logger.warning("Contact opted out: #{msg}")
{:error, %Surge.Error{type: type, message: msg}} ->
Logger.error("Surge error #{type}: #{msg}")
endWebhook handling
WebhookPlug for Phoenix
The SDK includes Surge.WebhookPlug that handles signature verification and event parsing. Add it to your endpoint.ex before Plug.Parsers:
# endpoint.ex
plug Surge.WebhookPlug,
at: "/webhook/surge",
handler: MyAppWeb.SurgeHandler,
secret: System.get_env("SURGE_WEBHOOK_SECRET")For runtime configuration, pass a tuple or function as the secret:
plug Surge.WebhookPlug,
at: "/webhook/surge",
handler: MyAppWeb.SurgeHandler,
secret: {Application, :get_env, [:myapp, :surge_webhook_secret]}WebhookHandler behaviour
Implement the Surge.WebhookHandler behaviour to process events. The callback receives a Surge.Events.Event struct with an atom type and a data field:
defmodule MyAppWeb.SurgeHandler do
@behaviour Surge.WebhookHandler
@impl true
def handle_event(%Surge.Events.Event{type: :message_received} = event) do
IO.inspect(event.data.body, label: "Received")
:ok
end
@impl true
def handle_event(%Surge.Events.Event{type: :contact_opted_out} = event) do
MyApp.handle_opt_out(event.data)
:ok
end
@impl true
def handle_event(_event), do: :ok
endThe callback should return :ok or {:ok, term} for success, or :error or {:error, reason} to signal a failure (which returns HTTP 400 to Surge).
Manual signature verification
If you're not using Surge.WebhookPlug, verify signatures with Surge.Webhook.construct_event/3:
case Surge.Webhook.construct_event(raw_body, signature_header, webhook_secret) do
{:ok, %Surge.Events.Event{} = event} ->
handle_event(event)
{:error, reason} ->
Logger.warning("Invalid webhook signature: #{inspect(reason)}")
endThe signature_header is the value of the surge-signature HTTP header, formatted as t=timestamp,v1=hex_signature.