Possinote Ruby SDK
Official Ruby SDK for the PossiNote API - Send SMS, emails, and schedule messages with ease.
Installation
Add this line to your application's Gemfile:
gem 'possinote'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install possinote
Quick Start
require 'possinote'
# Initialize the client with your API key
client = Possinote::Client.new(api_key: 'your_api_key_here')
# Send a single SMS
response = client.sms.send(
to: '+233244123456',
message: 'Hello from Possinote!',
sender_id: 'YourSenderID'
)
# Send a single email
response = client.email.send(
recipient: 'user@example.com',
subject: 'Welcome to Possinote',
content: '<h1>Hello!</h1><p>Welcome to our platform.</p>',
sender_name: 'Your Company'
)
API Reference
Authentication
All API requests require authentication using your API key:
client = Possinote::Client.new(api_key: 'your_api_key_here')
SMS Operations
Send Single SMS
response = client.sms.send(
to: '+233244123456',
message: 'Your message here',
sender_id: 'YourSenderID'
)
# Response
{
"success" => true,
"data" => {
"message_id" => "msg_123456789",
"to" => "+233244123456",
"status" => "queued",
"cost" => 1.0,
"created_at" => "2025-08-11T11:30:00Z"
}
}
Send Bulk SMS
response = client.sms.send_bulk(
sender_id: 'YourSenderID',
messages: [
{ to: '+233244123456', message: 'Message 1' },
{ to: '+233244123457', message: 'Message 2' }
]
)
# Response
{
"success" => true,
"data" => {
"batch_id" => "batch_123456789",
"total_messages" => 2,
"successful" => 2,
"failed" => 0,
"total_cost" => 2.0,
"messages" => [
{ "message_id" => "msg_1", "to" => "+233244123456", "status" => "queued" },
{ "message_id" => "msg_2", "to" => "+233244123457", "status" => "queued" }
]
}
}
Schedule Single SMS
response = client.sms.schedule(
recipient: '+233244123456',
message: 'Scheduled message',
sender_id: 'YourSenderID',
scheduled_at: '2025-08-11T12:00:00Z'
)
# Response
{
"success" => true,
"data" => {
"id" => "schedule_123456789",
"recipient" => "+233244123456",
"message" => "Scheduled message",
"scheduled_at" => "2025-08-11T12:00:00Z",
"status" => "pending",
"cost" => "1.0"
}
}
Schedule Bulk SMS
response = client.sms.schedule_bulk(
sender_id: 'YourSenderID',
messages: [
{ recipient: '+233244123456', message: 'Scheduled message 1' },
{ recipient: '+233244123457', message: 'Scheduled message 2' }
],
scheduled_at: '2025-08-11T12:00:00Z'
)
# Response
{
"success" => true,
"data" => {
"batch_id" => "batch_123456789",
"scheduled_count" => 2,
"total_cost" => 2.0,
"scheduled_at" => "2025-08-11T12:00:00Z",
"messages" => [
{ "id" => "schedule_1", "recipient" => "+233244123456", "status" => "pending" },
{ "id" => "schedule_2", "recipient" => "+233244123457", "status" => "pending" }
]
}
}
Email Operations
Send Single Email
response = client.email.send(
recipient: 'user@example.com',
subject: 'Welcome Email',
content: '<h1>Welcome!</h1><p>Thank you for joining us.</p>',
sender_name: 'Your Company'
)
# Response
{
"success" => true,
"message" => "Email queued for delivery",
"recipient" => "user@example.com",
"message_id" => "email_123456789"
}
Send Bulk Email
response = client.email.send_bulk(
subject: 'Newsletter',
content: '<h1>Newsletter</h1><p>This is our monthly newsletter.</p>',
recipients: ['user1@example.com', 'user2@example.com'],
sender_name: 'Your Company'
)
# Response
{
"success" => true,
"message" => "Bulk emails queued for delivery",
"queued_count" => 2,
"total_count" => 2,
"batch_id" => "batch_123456789",
"emails" => [
{ "message_id" => "email_1", "recipient" => "user1@example.com", "status" => "queued" },
{ "message_id" => "email_2", "recipient" => "user2@example.com", "status" => "queued" }
]
}
Scheduling Operations
Schedule Single Email
response = client.scheduling.schedule_email(
recipient: 'user@example.com',
subject: 'Scheduled Email',
content: '<h1>Scheduled Content</h1>',
scheduled_at: '2025-08-11T12:00:00Z',
sender_name: 'Your Company'
)
# Response
{
"success" => true,
"data" => {
"id" => "email_schedule_123456789",
"recipient" => "user@example.com",
"subject" => "Scheduled Email",
"scheduled_at" => "2025-08-11T12:00:00Z",
"status" => "pending",
"cost" => "1.0"
}
}
Schedule Bulk Individual Emails
response = client.scheduling.schedule_multiple_emails([
{
recipient: 'user1@example.com',
subject: 'Personalized Email 1',
content: '<h1>Hello User 1!</h1>',
scheduled_at: '2025-08-11T12:00:00Z',
sender_name: 'Your Company'
},
{
recipient: 'user2@example.com',
subject: 'Personalized Email 2',
content: '<h1>Hello User 2!</h1>',
scheduled_at: '2025-08-11T12:00:00Z',
sender_name: 'Your Company'
}
])
# Response
{
"success" => true,
"data" => {
"batch_id" => "batch_123456789",
"total_scheduled" => 2,
"total_cost" => 2.0,
"scheduled_emails" => [
{ "id" => "email_1", "recipient" => "user1@example.com", "status" => "pending" },
{ "id" => "email_2", "recipient" => "user2@example.com", "status" => "pending" }
]
}
}
Framework Integration
Rails Integration
1. Add to Gemfile
# Gemfile
gem 'possinote'
2. Configure in Application
# config/initializers/possinote.rb
require 'possinote'
# Initialize the client
POSSINOTE_CLIENT = Possinote::Client.new(
api_key: Rails.application.credentials.possinote[:api_key]
)
3. Use in Controllers
# app/controllers/notifications_controller.rb
class NotificationsController < ApplicationController
def send_sms
begin
response = POSSINOTE_CLIENT.sms.send(
to: params[:phone_number],
message: params[:message],
sender_id: 'YourBrand'
)
if response['success']
render json: { message: 'SMS sent successfully', data: response['data'] }
else
render json: { error: 'Failed to send SMS' }, status: :unprocessable_entity
end
rescue Possinote::AuthenticationError => e
render json: { error: 'Authentication failed' }, status: :unauthorized
rescue Possinote::PaymentRequiredError => e
render json: { error: 'Insufficient credits' }, status: :payment_required
rescue Possinote::ValidationError => e
render json: { error: e.message }, status: :bad_request
rescue => e
render json: { error: 'An error occurred' }, status: :internal_server_error
end
end
def send_bulk_sms
begin
response = POSSINOTE_CLIENT.sms.send_bulk(
sender_id: 'YourBrand',
messages: params[:messages] # Array of { to: phone, message: text }
)
render json: { message: 'Bulk SMS sent', data: response['data'] }
rescue => e
render json: { error: e.message }, status: :internal_server_error
end
end
def send_email
begin
response = POSSINOTE_CLIENT.email.send(
recipient: params[:email],
subject: params[:subject],
content: params[:content],
sender_name: 'Your Company'
)
render json: { message: 'Email sent successfully', data: response }
rescue => e
render json: { error: e.message }, status: :internal_server_error
end
end
end
4. Use in Services
# app/services/notification_service.rb
class NotificationService
def initialize
@client = POSSINOTE_CLIENT
end
def send_welcome_sms(user)
@client.sms.send(
to: user.phone_number,
message: "Welcome #{user.name}! Your account has been created successfully.",
sender_id: 'YourBrand'
)
end
def send_password_reset_email(user, reset_token)
@client.email.send(
recipient: user.email,
subject: 'Password Reset Request',
content: generate_password_reset_html(user, reset_token),
sender_name: 'Your Company'
)
end
def send_bulk_newsletter(users, newsletter_content)
messages = users.map do |user|
{
to: user.phone_number,
message: "Newsletter: #{newsletter_content[:title]}"
}
end
@client.sms.send_bulk(
sender_id: 'YourBrand',
messages: messages
)
end
def schedule_reminder_email(user, appointment)
@client.scheduling.schedule_email(
recipient: user.email,
subject: 'Appointment Reminder',
content: generate_appointment_reminder_html(appointment),
scheduled_at: appointment.datetime - 1.hour,
sender_name: 'Your Company'
)
end
private
def generate_password_reset_html(user, token)
<<~HTML
<h1>Password Reset Request</h1>
<p>Hello #{user.name},</p>
<p>You requested a password reset. Click the link below to reset your password:</p>
<a href="#{Rails.application.routes.url_helpers.reset_password_url(token: token)}">
Reset Password
</a>
<p>This link will expire in 1 hour.</p>
HTML
end
def generate_appointment_reminder_html(appointment)
<<~HTML
<h1>Appointment Reminder</h1>
<p>Hello #{appointment.user.name},</p>
<p>This is a reminder for your appointment:</p>
<ul>
<li><strong>Date:</strong> #{appointment.datetime.strftime('%B %d, %Y')}</li>
<li><strong>Time:</strong> #{appointment.datetime.strftime('%I:%M %p')}</li>
<li><strong>Location:</strong> #{appointment.location}</li>
</ul>
HTML
end
end
5. Use in Background Jobs
# app/jobs/send_notification_job.rb
class SendNotificationJob < ApplicationJob
queue_as :default
def perform(notification_type, user_id, options = {})
user = User.find(user_id)
service = NotificationService.new
case notification_type
when 'welcome_sms'
service.send_welcome_sms(user)
when 'password_reset_email'
service.send_password_reset_email(user, options[:reset_token])
when 'bulk_newsletter'
service.send_bulk_newsletter(options[:users], options[:content])
when 'scheduled_reminder'
service.schedule_reminder_email(user, options[:appointment])
end
end
end
# Usage in controller
SendNotificationJob.perform_later('welcome_sms', user.id)
SendNotificationJob.perform_later('password_reset_email', user.id, reset_token: token)
6. Environment Configuration
# config/credentials.yml.enc
possinote:
api_key: your_api_key_here
# Or use environment variables
# config/initializers/possinote.rb
POSSINOTE_CLIENT = Possinote::Client.new(
api_key: ENV['POSSINOTE_API_KEY']
)
Error Handling
The SDK provides specific exception classes for different error types:
begin
response = client.sms.send(to: '+233244123456', message: 'Hello', sender_id: 'SenderID')
rescue Possinote::AuthenticationError => e
puts "Authentication failed: #{e.message}"
rescue Possinote::PaymentRequiredError => e
puts "Payment required: #{e.message}"
rescue Possinote::RateLimitError => e
puts "Rate limit exceeded: #{e.message}"
rescue Possinote::ValidationError => e
puts "Validation error: #{e.message}"
rescue Possinote::APIError => e
puts "API error: #{e.message}"
end
Error Types
-
Possinote::AuthenticationError
- Invalid API key (401) -
Possinote::PaymentRequiredError
- Insufficient credits (402) -
Possinote::RateLimitError
- Rate limit exceeded (429) -
Possinote::ValidationError
- Invalid request data (400) -
Possinote::APIError
- Other API errors
Configuration
Base URL
The SDK uses the production API by default. For testing, you can modify the base URL:
# In lib/possinote/client.rb
BASE_URI = 'https://notifyapi.possitech.net/api/v1'
Timeout Settings
HTTP requests use default timeout settings. You can customize them in the client:
# The SDK uses HTTParty defaults
# You can modify timeout settings in lib/possinote/client.rb
Requirements
- Ruby >= 2.6.0
- HTTParty gem
- JSON gem
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/possitech/possinote-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Support
For support, email support@possitech.net or visit our documentation.
Changelog
1.0.0
- Initial release
- SMS sending and scheduling
- Email sending and scheduling
- Comprehensive error handling
- Full API coverage