Kirimi Ruby SDK
Official Ruby SDK for the Kirimi WhatsApp API. Zero runtime dependencies — uses only Ruby's built-in net/http.
Installation
Add to your Gemfile:
gem 'kirimi'
Then run:
bundle install
Or install directly:
gem install kirimi
Quick Start
require 'kirimi'
client = Kirimi::Client.new(
user_code: 'YOUR_USER_CODE',
secret: 'YOUR_SECRET'
)
resp = client.(
device_id: 'YOUR_DEVICE_ID',
phone: '628111222333',
message: 'Hello from Kirimi!'
)
puts resp.success? # => true
puts resp. # => "Message sent"
puts resp.data # => { ... }
Constructor
Kirimi::Client.new(
user_code: 'YOUR_USER_CODE', # required
secret: 'YOUR_SECRET', # required
base_url: 'https://api.kirimi.id', # optional, default
timeout: 30 # optional, seconds
)
All Methods
WhatsApp Unofficial
# Send text/media message
client.(device_id:, phone:, message:, media_url: nil)
# Send file via multipart (accepts File, StringIO, or file path string)
client.(device_id:, phone:, file:, file_name:, message: nil)
# Send message without typing indicator
client.(device_id:, phone:, message:, media_url: nil)
WABA (WhatsApp Business API)
client.(device_id:, phone:, message:)
Devices
client.list_devices
client.device_status(device_id:)
client.device_status_enhanced(device_id:)
User
client.user_info
Contacts
client.save_contact(phone:, name: nil, email: nil)
OTP (V1)
# Generate & send OTP
client.generate_otp(
device_id:,
phone:,
otp_length: 6, # optional
otp_type: 'numeric', # optional: numeric, alphabetic, alphanumeric
custom_otp_message: nil # optional
)
# Validate OTP
client.validate_otp(device_id:, phone:, otp:)
OTP (V2)
# Send OTP via WABA template or device
client.send_otp_v2(
phone:,
device_id:,
method: 'device', # optional: device, waba
app_name: 'MyApp', # optional
template_code: nil, # optional, for waba method
custom_message: nil # optional, for device method
)
# Verify OTP
client.verify_otp_v2(phone:, otp_code:)
Broadcast
# phones accepts String or Array (Array auto-joined with comma)
client.(
device_id:,
phones: ['628111', '628222', '628333'],
message: 'Promo!',
delay: 2 # optional, seconds between messages
)
Deposits
client.list_deposits(status: nil) # status: nil, 'paid', 'unpaid', 'expired'
client.list_packages
Response Object
All methods return a Kirimi::Response instance:
resp = client.(device_id: 'DEV', phone: '628xxx', message: 'hi')
resp.success? # => true / false (boolean method)
resp.success # => true / false (raw value)
resp.data # => Hash or nil
resp. # => String
resp.raw # => full parsed Hash
Error Handling
begin
resp = client.(device_id: 'DEV', phone: '628xxx', message: 'hi')
rescue Kirimi::ApiError => e
puts e.status_code # => 401
puts e. # => "Unauthorized"
puts e.response_data # => parsed response body
rescue Kirimi::NetworkError => e
puts "Network problem: #{e.}"
rescue Kirimi::Error => e
puts "SDK error: #{e.}"
end
Rails Integration
Application configuration
# config/initializers/kirimi.rb
KIRIMI_CLIENT = Kirimi::Client.new(
user_code: ENV.fetch('KIRIMI_USER_CODE'),
secret: ENV.fetch('KIRIMI_SECRET')
)
Controller example
class NotificationsController < ApplicationController
def send_otp
resp = KIRIMI_CLIENT.generate_otp(
device_id: params[:device_id],
phone: params[:phone],
otp_length: 6,
otp_type: 'numeric'
)
if resp.success?
render json: { sent: true }
else
render json: { sent: false, error: resp. }, status: :unprocessable_entity
end
rescue Kirimi::ApiError => e
render json: { error: e. }, status: e.status_code
end
end
Background Job example
class SendWhatsAppJob < ApplicationJob
queue_as :default
def perform(device_id, phone, )
KIRIMI_CLIENT.(device_id: device_id, phone: phone, message: )
rescue Kirimi::ApiError, Kirimi::NetworkError => e
Rails.logger.error "[Kirimi] #{e.class}: #{e.}"
raise # re-raise to trigger job retry
end
end
License
MIT — see LICENSE.