Disclaimer: This gem is an independent, unofficial Ruby client library. It is not affiliated with, endorsed by, or supported by efacturapty or the Dirección General de Ingresos (DGI) of Panama. For official documentation and support, visit efacturapty.com and the DGI e-factura portal.
AI-generated code notice: This library was generated with the assistance of AI tools. Review the source carefully before using it in production, and test against the sandbox environment before going live.
Ruby client gem for Panama's DGI e-invoicing (e-factura / SFEP) system, powered by the efacturapty service.
Handles authentication, PAC authorization, invoice creation, cancellation, file downloads, and all reference catalogs — compatible with Ruby 2.6+ / Rails 5.2+ and modern stacks.
- Installation
- Quick start
- Configuration
- Authentication
- Usage
- Response objects
- Error handling
- Development
Add to your Gemfile:
gem "efacturapty"Or install directly:
gem install efacturaptyrequire "efacturapty"
Efacturapty.configure do |c|
c.api_key = ENV["EFACTURAPTY_API_KEY"]
end
client = Efacturapty.client
# List countries catalog
countries = client.catalogs.countries
# Create and authorize an invoice
response = client.invoices.create(invoice_payload, include_qr: true)
puts response.cufe # CUFE assigned by DGI
puts response.autorizada # true when successfully authorizedRun the install generator:
rails generate efacturapty:installThis creates config/initializers/efacturapty.rb:
Efacturapty.configure do |config|
config.api_key = ENV.fetch("EFACTURAPTY_API_KEY", nil)
# config.open_timeout = 5
# config.read_timeout = 30
# config.logger = Rails.logger
endrequire "efacturapty"
Efacturapty.configure do |c|
c.api_key = "your-api-key"
end
client = Efacturapty.clientclient = Efacturapty::Client.new(
api_key: "your-api-key",
logger: Logger.new($stdout)
)| Option | Default | Description |
|---|---|---|
api_key |
— | Required. Bearer token issued by efacturapty |
api_base_url |
https://api.efacturapty.com |
Override API base URL |
open_timeout |
5 |
TCP connect timeout (seconds) |
read_timeout |
30 |
Read timeout (seconds) |
logger |
nil |
Any Logger-compatible object |
Set config.api_key to the Bearer token issued by your efacturapty account.
The token is sent as the Authorization: Bearer … header on every request.
No token exchange or refresh logic is needed.
Accepts a plain Ruby Hash matching the DGI InvoiceRequest structure.
See docs/invoices.md for the full payload schema.
resp = client.invoices.create(
{
"datosGenerales" => {
"tipoDocumento" => "01",
"naturalezaOperacion" => "01",
# ...
},
"listaItems" => [ { ... } ],
"totales" => { ... }
},
include_qr: true, # include QR image (Base64) in response
include_xml: true # include raw authorized XML in response
)
resp.cufe # => "CUFE-xxxx..."
resp.autorizada # => true
resp.qrContent # => "https://efacturapty.com/qr?cufe=..."
resp.qrContentImageBase64 # => "iVBORw0KGgo..."
resp.xml # => "<?xml version=\"1.0\"...>"Response keys are looked up as-is (no camelCase→snake_case translation), so use the exact
DGI field name — resp.qrContentImageBase64, not resp.qr_content_image_base64 — or hash-style
resp["qrContentImageBase64"].
resp = client.invoices.create_from_xml(xml_string)page = client.invoices.list(
date_from: "2026-01-01",
date_to: "2026-06-30",
status: "Authorized",
page: 1,
page_size: 50
)Available filter keys: date_from, date_to, ruc, name, status, page, page_size, and
environment (deprecated by the API, accepted but discouraged). Any other key is silently
dropped rather than sent as a meaningless query param — see docs/invoices.md
for the full list of what earlier gem versions accepted but the real API never supported.
Pass locale: "en" to override the Accept-Language header.
resp = client.invoices.find(cufe_id)resp = client.invoices.authorization(cufe)
resp = client.invoices.authorization_admin(cufe) # admin: any taxpayerresp = client.invoices.qr_image(cufe) # Base64-encoded PNGpdf = client.invoices.cafe_file(cufe_id) # => binary PDF String
xml = client.invoices.xml_file(cufe_id) # => binary XML String
xml = client.invoices.xml_from_dgi(cufe) # => XML from DGI
html = client.invoices.html_cafe(cufe_id) # => Response (HTML body)resp = client.invoices.taxpayer_response(invoice_id)resp = client.invoice_events.cancel(
cufe: "CUFE-xxxx...",
reason: "Error en los datos del receptor"
)client.catalogs.countries # list of countries
client.catalogs.currencies # list of currencies
client.catalogs.locations # districts / provinces / corregimientos
client.catalogs.cpbs_families # CPBS product/service families
client.catalogs.cpbs_segments # CPBS product/service segmentsAll non-binary endpoints return an Efacturapty::Response object.
Keys are accessible as methods or with []:
resp = client.catalogs.countries
resp["name"] # hash-style
resp.name # method-style
resp.to_h # underlying Hash
resp.to_a # underlying Array (for list responses)
resp.status # HTTP status codebegin
client.invoices.create(payload)
rescue Efacturapty::ValidationError => e
# client-side pre-flight check failed — no HTTP request was made
puts e.errors # Array of every violation found
rescue Efacturapty::AuthenticationError => e
# 401 or bad credentials
puts e.message
rescue Efacturapty::BadRequestError => e
# 400 / 422
puts e.body # parsed response body
puts e.status # 400
rescue Efacturapty::NotFoundError
# 404
rescue Efacturapty::RateLimitError
# 429
rescue Efacturapty::ServerError
# 5xx
rescue Efacturapty::ApiError => e
# any other API error
rescue Efacturapty::ConfigurationError
# missing credentials
rescue Efacturapty::Error => e
# catch-all
endEfacturapty::Error
├── ConfigurationError
├── ValidationError (client-side only — has .errors, no HTTP status/body)
└── ApiError
├── AuthenticationError (401)
├── BadRequestError (400, 422)
├── NotFoundError (404)
├── RateLimitError (429)
└── ServerError (5xx)
git clone https://github.com/mopx/efacturapty-ruby
cd efacturapty-ruby
bundle install
bundle exec rspec # run tests
bundle exec rubocop # lint
bin/console # interactive console with gem loaded
gem build efacturapty.gemspec # build .gem fileRuntime requires Ruby 2.6+. Development tools (RuboCop, RSpec) run on
modern Ruby. Use a version manager (rbenv / rvm) to test on Ruby 2.6.10 with
bundle exec rspec.
Bug reports and pull requests welcome at https://github.com/mopx/efacturapty-ruby.
MIT — see LICENSE.