Project

kirimi

0.0
The project is in a healthy, maintained state
Send WhatsApp messages, OTP, broadcasts, and more via the Kirimi API.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 13.0
 Project Readme

Kirimi Ruby SDK

Gem Version License: MIT

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.send_message(
  device_id: 'YOUR_DEVICE_ID',
  phone:     '628111222333',
  message:   'Hello from Kirimi!'
)

puts resp.success?  # => true
puts resp.message   # => "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.send_message(device_id:, phone:, message:, media_url: nil)

# Send file via multipart (accepts File, StringIO, or file path string)
client.send_message_file(device_id:, phone:, file:, file_name:, message: nil)

# Send message without typing indicator
client.send_message_fast(device_id:, phone:, message:, media_url: nil)

WABA (WhatsApp Business API)

client.send_waba_message(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.broadcast_message(
  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.send_message(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.message   # => String
resp.raw       # => full parsed Hash

Error Handling

begin
  resp = client.send_message(device_id: 'DEV', phone: '628xxx', message: 'hi')
rescue Kirimi::ApiError => e
  puts e.status_code    # => 401
  puts e.message        # => "Unauthorized"
  puts e.response_data  # => parsed response body
rescue Kirimi::NetworkError => e
  puts "Network problem: #{e.message}"
rescue Kirimi::Error => e
  puts "SDK error: #{e.message}"
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.message }, status: :unprocessable_entity
    end
  rescue Kirimi::ApiError => e
    render json: { error: e.message }, status: e.status_code
  end
end

Background Job example

class SendWhatsAppJob < ApplicationJob
  queue_as :default

  def perform(device_id, phone, message)
    KIRIMI_CLIENT.send_message(device_id: device_id, phone: phone, message: message)
  rescue Kirimi::ApiError, Kirimi::NetworkError => e
    Rails.logger.error "[Kirimi] #{e.class}: #{e.message}"
    raise  # re-raise to trigger job retry
  end
end

License

MIT — see LICENSE.