Conexa Ruby
Ruby client for the Conexa API - Billing and subscription management platform.
Installation
Add to your Gemfile:
gem 'conexa'Or install directly:
gem install conexaConfiguration
Conexa.configure do |config|
config.subdomain = 'YOUR_SUBDOMAIN' # your-company.conexa.app
config.api_token = 'YOUR_API_TOKEN' # Application Token from Conexa
endAuthentication Methods
- Application Token (recommended): Created in Conexa at Config > Integrações > API / Token
-
Username/Password: Use the
/authendpoint to get a JWT token
Quick Start
require 'conexa'
Conexa.configure do |config|
config.subdomain = 'mycompany'
config.api_token = ENV['CONEXA_API_TOKEN']
end
# List customers
customers = Conexa::Customer.all
customers.data.each do |customer|
puts "#{customer.customer_id}: #{customer.name}"
end
# Get a specific customer
customer = Conexa::Customer.find(127)
puts customer.name
puts customer.address.cityConvention
This gem follows Ruby conventions:
-
Parameters: Use
snake_casewhen calling methods - the gem automatically converts tocamelCasefor the API -
Responses: API responses are converted from
camelCasetosnake_case -
Backwards compatibility:
camelCasemethods are aliased (e.g.,customer.customer_idandcustomer.customerIdboth work)
Resources
Customer
# Create a customer (Legal Person - PJ)
customer = Conexa::Customer.create(
company_id: 3,
name: 'Empresa ABC Ltda',
trade_name: 'ABC',
cell_number: '11999998888',
has_login_access: false,
legal_person: {
cnpj: '99.557.155/0001-90',
foundation_date: '2020-06-12'
},
address: {
zip_code: '13058-111',
state: 'SP',
city: 'Campinas',
street: 'Rua Principal',
number: '100',
neighborhood: 'Centro'
},
phones: ['(11) 3333-4444'],
emails_message: ['contato@empresa.com'],
emails_financial_messages: ['financeiro@empresa.com']
)
puts customer.id # => 114
# Create a customer (Natural Person - PF)
customer = Conexa::Customer.create(
company_id: 3,
name: 'João Silva',
natural_person: {
cpf: '516.079.209-05',
birth_date: '1990-05-15',
profession: 'Developer'
},
has_login_access: true,
login: 'joao.silva',
password: 'SecurePass123!'
)
# Retrieve customer
customer = Conexa::Customer.find(127)
customer.name # => "Empresa ABC Ltda"
customer.company_id # => 3
customer.is_active # => true
customer.address.city # => "Campinas"
customer.legal_person['cnpj'] # => "99.557.155/0001-90"
# Update customer
customer = Conexa::Customer.find(127)
customer.name = 'New Name'
customer.cell_number = '11888887777'
customer.save
# List customers with filters (new pagination)
customers = Conexa::Customer.all(
company_id: [3],
is_active: true,
limit: 20
)Contract
# Create a contract
contract = Conexa::Contract.create(
customer_id: 127,
plan_id: 5,
start_date: '2024-01-01',
payment_day: 10,
invoicing_method_id: 1
)
# Create contract with custom items
contract = Conexa::Contract.create_with_products(
customer_id: 127,
start_date: '2024-01-01',
payment_day: 10,
items: [
{ product_id: 101, quantity: 1, amount: 299.90 },
{ product_id: 102, quantity: 2, amount: 49.90 }
]
)
# Retrieve contract
contract = Conexa::Contract.find(456)
# Cancel contract
Conexa::Contract.cancel(456, cancel_date: '2024-12-31')Sale (One-time)
# Create a one-time sale
sale = Conexa::Sale.create(
customer_id: 450,
requester_id: 458,
product_id: 2521,
quantity: 1,
amount: 80.99,
reference_date: '2024-09-24T17:24:00-03:00',
notes: 'WhatsApp order'
)
puts sale.id # => 188481
# Retrieve sale
sale = Conexa::Sale.find(188510)
sale.status # => "notBilled"
sale.amount # => 80.99
sale.discount_value # => 69.21
# List sales
sales = Conexa::Sale.all(
customer_id: [450, 216],
status: 'notBilled',
date_from: '2024-01-01',
date_to: '2024-12-31',
page: 1,
size: 20
)
# Update sale
sale = Conexa::Sale.find(188510)
sale.quantity = 2
sale.amount = 150.00
sale.save
# Delete sale (only if not billed)
Conexa::Sale.destroy(188510)Recurring Sale
# Create recurring sale
recurring = Conexa::RecurringSale.create(
customer_id: 127,
product_id: 101,
quantity: 1,
start_date: '2024-01-01'
)
# List recurring sales for a contract
Conexa::RecurringSale.all(contract_id: 456)Charge
# Retrieve charge
charge = Conexa::Charge.find(789)
charge.status # => "paid"
charge.amount # => 299.90
charge.due_date # => "2024-02-10"
# List charges
charges = Conexa::Charge.all(
customer_id: [127],
status: 'pending',
due_date_from: '2024-01-01',
due_date_to: '2024-12-31'
)
# Cancel charge
Conexa::Charge.cancel(789)
# Send charge by email
Conexa::Charge.send_email(789)Bill (Invoice)
# Retrieve bill
bill = Conexa::Bill.find(101)
# List bills
bills = Conexa::Bill.all(
customer_id: [127],
page: 1,
size: 50
)Plan
# List plans
plans = Conexa::Plan.all(company_id: [3])
# Retrieve plan
plan = Conexa::Plan.find(5)
plan.name # => "Plano Básico"
plan.price # => 99.90Product
# List products
products = Conexa::Product.all(company_id: [3], limit: 50)
# Retrieve product
product = Conexa::Product.find(101)
# Create product
product = Conexa::Product.create(name: 'Novo Produto', company_id: 3)
# Delete product
Conexa::Product.destroy(101)Receiving Method
methods = Conexa::ReceivingMethod.all(limit: 50)
method = Conexa::ReceivingMethod.find(11)
method.name # => "Cartão de Crédito"Payment Method
methods = Conexa::PaymentMethod.all(limit: 50)
method = Conexa::PaymentMethod.find(2)Bill Category / Subcategory
categories = Conexa::BillCategory.all(limit: 50)
subcategories = Conexa::BillSubcategory.all(limit: 50)Cost Center
centers = Conexa::CostCenter.all(limit: 50)
center = Conexa::CostCenter.find(11)Account
accounts = Conexa::Account.all(limit: 50)
account = Conexa::Account.find(23)Service Category
categories = Conexa::ServiceCategory.all(limit: 50)
category = Conexa::ServiceCategory.find(1)Room Booking
# List bookings
bookings = Conexa::RoomBooking.all(limit: 20)
# Create booking
booking = Conexa::RoomBooking.create(room_id: 5, customer_id: 127)
# Cancel booking
Conexa::RoomBooking.cancel(143063)
# Checkin
Conexa::RoomBooking.checkin(room_id: 5, customer_id: 127)Credit Card
# Add credit card to customer
card = Conexa::CreditCard.create(
customer_id: 127,
card_number: '4111111111111111',
cardholder_name: 'JOAO SILVA',
expiration_month: '12',
expiration_year: '2025',
cvv: '123'
)
# List customer's cards
cards = Conexa::CreditCard.all(customer_id: 127)
# Delete card
Conexa::CreditCard.destroy(card_id)Company (Unit)
# List companies/units
companies = Conexa::Company.all
# Retrieve company
company = Conexa::Company.find(3)
company.name # => "Matriz"
company.document # => "12.345.678/0001-90"Pagination
New Pagination (recommended) — limit/offset/hasNext
result = Conexa::Customer.all(limit: 50)
result.data # Array of customers
result.pagination.limit # => 50
result.pagination.offset # => 0
result.has_next? # => true/false
# Iterate through all pages using next_page
result = Conexa::Customer.all(limit: 50)
loop do
result.data.each { |customer| process(customer) }
break unless result.has_next?
result = result.next_page
end
# Or manually with offset
offset = 0
loop do
result = Conexa::Customer.all(limit: 50, offset: offset)
result.data.each { |customer| process(customer) }
break unless result.has_next?
offset += 50
endLegacy Pagination (deprecated — will be removed 2026-08-01)
# Still works but emits a deprecation warning
result = Conexa::Customer.all(page: 1, size: 20)
result.pagination.current_page # => 1
result.pagination.total_pages # => 10Migration Guide: Legacy → New Pagination
The legacy page/size pagination is deprecated and will be removed on 2026-08-01. Follow these steps to migrate:
1. Replace page/size with limit/offset
# BEFORE (legacy — deprecated)
result = Conexa::Customer.all(page: 1, size: 50)
result = Conexa::Customer.all(page: 2, size: 50)
# AFTER (new)
result = Conexa::Customer.all(limit: 50) # offset defaults to 0
result = Conexa::Customer.all(limit: 50, offset: 50) # second pageConversion formula: offset = (page - 1) * size
2. Update pagination metadata access
# BEFORE (legacy)
result.pagination # => { "page" => 1, "size" => 50, "total" => 150 }
total_pages = (result.pagination["total"].to_f / size).ceil
# AFTER (new)
result.pagination.limit # => 50
result.pagination.offset # => 0
result.pagination.has_next # => true/false3. Update iteration loops
# BEFORE (legacy)
page = 1
loop do
result = Conexa::Customer.all(page: page, size: 100)
break if result.empty?
result.data.each { |c| process(c) }
page += 1
end
# AFTER (new — using next_page)
result = Conexa::Customer.all(limit: 100)
loop do
result.data.each { |c| process(c) }
break unless result.has_next?
result = result.next_page
end4. Remove positional arguments
# BEFORE (legacy positional args)
Conexa::Customer.all(2, 50) # page 2, size 50
Conexa::Customer.find_by({}, 1, 20) # page 1, size 20
# AFTER (new keyword args)
Conexa::Customer.all(limit: 50, offset: 50)
Conexa::Customer.find_by(limit: 20)Quick reference
| Legacy | New |
|---|---|
page: 1, size: 50 |
limit: 50 (offset defaults to 0) |
page: N, size: S |
limit: S, offset: (N-1)*S |
pagination["total"] |
pagination.has_next |
pagination["page"] |
pagination.offset |
Positional (page, size)
|
Keyword limit:, offset:
|
Error Handling
begin
customer = Conexa::Customer.create(name: '')
rescue Conexa::ValidationError => e
# Field validation errors (400)
puts e.message
rescue Conexa::NotFound => e
# Resource not found (404)
puts e.message
rescue Conexa::ResponseError => e
# API response error (4xx/5xx)
puts e.message
rescue Conexa::RequestError => e
# Request-level error (invalid params, etc.)
puts e.message
rescue Conexa::ConnectionError => e
# Network/connection error
puts e.message
rescue Conexa::ConexaError => e
# Generic Conexa error (catch-all)
puts e.message
endRate Limiting
The Conexa API has a limit of 100 requests per minute (changing to 60 requests per minute on 2026-04-27). Response headers include:
-
X-Rate-Limit-Limit: Maximum requests in 60s -
X-Rate-Limit-Remaining: Remaining requests in 60s -
X-Rate-Limit-Reset: Seconds until reset
Documentation
- Conexa Website
- API Documentation
- Postman Collection
- Discord Community - Conexa for Developers
- REFERENCE.md - Complete API reference for LLMs/AI agents
Development
# Install dependencies
bundle install
# Run tests
bundle exec rspec
# Run linter
bundle exec rubocopContributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -am 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Create a Pull Request
License
MIT License. See LICENSE for details.
Changelog
See CHANGELOG.md for release history.