> ## Documentation Index
> Fetch the complete documentation index at: https://docs.surge.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Ruby SDK

> Install the Ruby SDK with Sorbet types, send messages, paginate, handle errors, and verify webhooks in Rails.

The Ruby SDK ships with Sorbet type signatures for every endpoint, so editors and `srb tc` can flag bad payloads before runtime. It's published as `surge_api` on RubyGems and supports Ruby 3.1 and newer.

This page covers installing the gem, sending your first request, paginating list endpoints, rescuing typed errors, and verifying webhook signatures inside a Rails controller.

## Install and authenticate

Add to your Gemfile:

```ruby Gemfile theme={null}
gem "surge_api"
```

```bash theme={null}
bundle install
```

Set your API key:

```bash theme={null}
export SURGE_API_KEY=sk_live_your_key_here
```

```ruby theme={null}
require "surge_api"

surge = SurgeAPI::Client.new
```

Sorbet type signatures are included for typed Ruby projects.

## Your first request

```ruby theme={null}
message = surge.messages.create(
  "acct_01jrzhe8d9enptypyx360pcmxj",
  to: "+18015551234",
  body: "Your appointment is confirmed for Friday at 2pm."
)

puts message.id      # msg_01j...
puts message.status  # "sent"
```

## Pagination

The SDK provides an auto-paginating enumerator:

```ruby theme={null}
# Iterates through all messages
surge.messages.list("acct_01j...").each do |message|
  puts "#{message.id}: #{message.status}"
end
```

For manual pagination:

```ruby theme={null}
page = surge.messages.list_page("acct_01j...", limit: 25)
page.data.each { |m| puts m.id }
puts page.pagination.next_cursor
```

## Retries and timeouts

```ruby theme={null}
surge = SurgeAPI::Client.new(
  max_retries: 5,
  timeout: 30 # seconds
)
```

## Error handling

```ruby theme={null}
begin
  surge.messages.create(
    "acct_01j...",
    to: "+18015551234",
    body: "Hello"
  )
rescue SurgeAPI::APIStatusError => e
  puts e.status        # 422
  puts e.error.type    # "opted_out"
  puts e.error.message
rescue SurgeAPI::AuthenticationError => e
  puts "Invalid API key"
end
```

## Webhooks

```ruby theme={null}
require "surge_api/webhooks"

wh = SurgeAPI::Webhook.new(ENV["SURGE_WEBHOOK_SECRET"])

# Rails example:
class WebhooksController < ApplicationController
  skip_before_action :verify_authenticity_token

  def create
    begin
      event = wh.verify(request.raw_post, request.headers)
    rescue SurgeAPI::WebhookVerificationError
      head :bad_request and return
    end

    case event["type"]
    when "message.received"
      handle_inbound(event["data"])
    when "contact.opted_out"
      handle_opt_out(event["data"])
    end

    head :ok
  end
end
```
