The official Ruby client for the Volara API. Send WhatsApp and omnichannel messages, manage conversations and contacts, run broadcasts, search your knowledge base, read metrics, and provision agency client orgs.
Built on the Ruby standard library — no runtime gems to install. Works on Ruby 3.0+.
gem install volaraOr add it to your Gemfile:
gem "volara"Grab an API key from your Volara dashboard. Pass it directly, or set
VOLARA_API_KEY and let the client pick it up.
client = Volara::Client.new(api_key: "sk_live_...")
# or, with VOLARA_API_KEY set in the environment:
client = Volara::Client.newSend your first WhatsApp message in a few lines:
require "volara"
client = Volara::Client.new # reads VOLARA_API_KEY
message = client.messages.send("conv_123", text: "Halo from Ruby!")
puts message[:id]# List conversations
client.conversations.list(status: "open", per_page: 25)[:data].each do |conv|
puts conv[:id]
end
# Page through every conversation without managing offsets
client.conversations.each { |conv| puts conv[:id] }
# Fetch one conversation
client.conversations.get("conv_123")
# Create a contact (phone in E.164)
client.contacts.create(name: "Sari", phone_number: "+6281234567890", source: "website")
# Search the knowledge base
client.knowledge.search("refund policy", scope: "faqs")
# Start a broadcast
client.broadcasts.create(title: "Promo Lebaran", message_content: "Diskon 20% hari ini!")
# Dashboard metrics
client.metrics.dashboard
# Agency (needs an agency-scoped key)
client.agency.overview
client.agency.clients.list
client.agency.clients.create_org(name: "Toko Sari")Responses come back as hashes with symbol keys (e.g. message[:id]). List
endpoints return { data: [...], total:, page:, limit: } when the API includes
that metadata.
Need an endpoint the SDK doesn't model yet? Use the escape hatch:
client.request("/tickets", query: { status: "open" })Verify the signature against the raw request body before trusting an event.
The header may be bare hex or carry a sha256= prefix — both are accepted, and
the comparison is constant-time.
ok = Volara::Webhooks.verify(
payload: raw_request_body,
signature: request.get_header("HTTP_X_VOLARA_SIGNATURE").to_s,
secret: ENV.fetch("VOLARA_WEBHOOK_SECRET")
)In Sinatra:
post "/webhooks/volara" do
raw = request.body.read
sig = request.env["HTTP_X_VOLARA_SIGNATURE"].to_s
halt 401 unless Volara::Webhooks.verify(
payload: raw, signature: sig, secret: ENV.fetch("VOLARA_WEBHOOK_SECRET")
)
event = JSON.parse(raw)
# handle event...
status 200
endEvery non-2xx response, plus network failures and timeouts, raises a
Volara::Error. Timeouts and connection failures use the Volara::TimeoutError
and Volara::ConnectionError subclasses, so you can catch the base class for
everything.
begin
client.conversations.get("missing")
rescue Volara::Error => err
warn err.message # human-readable
warn err.status # HTTP status (0 for network/timeout)
warn err.code # machine code, e.g. "VLR-..."
warn err.request_id # quote this when contacting support
end- Automatic retries with exponential backoff on
408,425,429, and5xx, plus transient network errors.Retry-Afteris honored when present. - Configurable per-request timeout (
timeout:, default 30s) and retry budget (max_retries:, default 2). - An
Idempotency-Keyis generated automatically for every write, so retries never create duplicates. Pass your own withidempotency_key:.
client = Volara::Client.new(timeout: 10, max_retries: 4)MIT — see LICENSE.