Ruby SDK
Offizielles Ruby SDK für thelawin.dev.
Erfordert Ruby 3.0+
Installation
In deinem Gemfile:
ruby
gem 'thelawin', '~> 0.2'Dann:
bash
bundle installOder direkt installieren:
bash
gem install thelawinSchnellstart
ruby
require 'thelawin'
client = Thelawin::Client.new(api_key: 'env_sandbox_xxx')
result = client.invoice
.number('2026-001')
.date('2026-01-15')
.seller(name: 'Acme GmbH', vat_id: 'DE123456789', city: 'Berlin', country: 'DE')
.buyer(name: 'Kunde AG', city: 'München', country: 'DE')
.add_item(description: 'Beratung', quantity: 8, unit: 'HUR', unit_price: 150, vat_rate: 19)
.template('minimal')
.generate
if result.success?
result.save_pdf('./rechnung.pdf')
puts "Erstellt: #{result.filename}"
puts "Format: #{result.format.format_used}"
else
result.errors.each { |e| puts "#{e[:path]}: #{e[:message]}" }
endClient-Optionen
ruby
client = Thelawin::Client.new(
api_key: 'env_sandbox_xxx',
environment: :production, # :production oder :preview
timeout: 30 # optional, Sekunden
)Umgebungen
| Umgebung | URL | Beschreibung |
|---|---|---|
:production | https://api.thelawin.dev | Produktions-API (Standard) |
:preview | https://api.preview.thelawin.dev:3080 | Preview/Staging-API |
ruby
# Globale Konfiguration
Thelawin.configure do |config|
config.api_key = 'env_sandbox_xxx'
config.environment = :preview
end
# Oder pro Client
client = Thelawin::Client.new(api_key: 'env_sandbox_xxx', environment: :preview)
# Umgebung prüfen
client.preview? # => true
client.production? # => falseUnterstützte Formate
| Format | Beschreibung | Ausgabe |
|---|---|---|
auto | Auto-Erkennung basierend auf Ländern (Standard) | PDF oder XML |
zugferd | ZUGFeRD 2.3 (Deutschland/EU) | PDF/A-3 + CII XML |
facturx | Factur-X 1.0 (Frankreich) | PDF/A-3 + CII XML |
xrechnung | XRechnung 3.0 (Deutsche B2G) | PDF/A-3 + UBL XML |
pdf | Einfaches PDF ohne XML | |
ubl | UBL 2.1 Invoice | nur XML |
cii | UN/CEFACT CII | nur XML |
peppol | Peppol BIS Billing 3.0 | nur XML |
fatturapa | FatturaPA 1.2.1 (Italien) | nur XML |
Builder API
Rechnungsdetails
ruby
client.invoice
.number('2026-001') # Erforderlich
.date('2026-01-15') # Erforderlich, String oder Date
.due_date('2026-02-15') # Optional
.currency('EUR') # Standard: 'EUR'
.notes('Vielen Dank!') # OptionalFormat & Profil
ruby
.format('zugferd') # 'auto', 'zugferd', 'facturx', 'xrechnung', 'pdf', 'ubl', 'cii', 'peppol', 'fatturapa'
.profile('en16931') # 'minimum', 'basic_wl', 'basic', 'en16931', 'extended'Parteien
ruby
.seller(
name: 'Acme GmbH', # Erforderlich
vat_id: 'DE123456789', # Erforderlich für ZUGFeRD
street: 'Hauptstraße 1',
city: 'Berlin', # Erforderlich
postal_code: '10115',
country: 'DE', # Erforderlich
email: 'rechnung@acme.de', # Erforderlich für XRechnung
peppol_id: '0088:123...', # Für Peppol
codice_fiscale: '...', # Für FatturaPA
)
.buyer(
name: 'Kunde AG', # Erforderlich
vat_id: 'DE987654321',
city: 'München', # Erforderlich
country: 'DE', # Erforderlich
codice_destinatario: '...', # Für FatturaPA
pec: 'cliente@pec.it' # Für FatturaPA
)Positionen
ruby
.add_item(
description: 'Beratung', # Erforderlich
quantity: 8, # Erforderlich
unit: 'HUR', # Erforderlich (C62=Stück, HUR=Stunde, DAY=Tag)
unit_price: 150.00, # Erforderlich
vat_rate: 19.0, # Erforderlich
natura: 'N2.2' # Für FatturaPA (MwSt-Befreiung)
)Format-spezifische Felder
ruby
.leitweg_id('04011000-12345-67') # XRechnung: B2G-Routing
.buyer_reference('PO-12345') # Peppol: Bestellreferenz
.tipo_documento('TD01') # FatturaPA: Dokumenttyp (TD01=Rechnung)Anpassung
ruby
.template('minimal') # 'minimal', 'classic', 'compact'
.locale('de') # 'en', 'de', 'fr', 'es', 'it'
.accent_color('#8b5cf6')
.footer_text('Vielen Dank!')Logo
ruby
# Aus Datei (auto Base64)
.logo_file('./logo.png')
.logo_file('./logo.png', width_mm: 30)
# Aus Base64
.logo_base64('iVBORw0KGgo...', width_mm: 30)Ergebnis-Handling
ruby
result = builder.generate
if result.success?
puts result.filename # 'rechnung-2026-001.pdf' oder '.xml'
puts result.format.format_used # 'zugferd', 'fatturapa', etc.
puts result.format.profile # 'EN16931'
puts result.format.version # '2.3'
# In Datei speichern
result.save_pdf('./rechnung.pdf') # oder result.save('./rechnung.xml')
# Bytes abrufen
pdf_bytes = result.to_bytes
# Data URL abrufen
data_url = result.to_data_url
# Prüfen ob nur XML
if result.xml_only?
# XML-only Formate (UBL, Peppol, FatturaPA, etc.)
end
# Rechtliche Hinweise
result.warnings.each do |warning|
puts "#{warning.code}: #{warning.message}"
end
else
result.errors.each do |error|
puts "#{error[:path]}: #{error[:message]}"
end
endVor-Validierung (Dry-Run)
Rechnungsdaten validieren ohne PDF zu erzeugen:
ruby
result = client.invoice
.number('2026-001')
.date('2026-01-15')
.seller(name: 'Acme', country: 'DE')
.buyer(name: 'Kunde', country: 'IT')
.add_item(description: 'Service', quantity: 1, unit_price: 100)
.format('fatturapa')
.validate # Gibt DryRunResult zurück
if result.valid?
puts "Gültig! Würde erzeugen: #{result.format.format_used}"
else
result.errors.each { |e| puts e }
endFehlerbehandlung
ruby
begin
result = client.invoice.generate
rescue Thelawin::QuotaExceededError
puts 'Kontingent erschöpft, bitte Plan upgraden'
rescue Thelawin::NetworkError => e
puts "Netzwerkfehler: #{e.message}"
rescue Thelawin::ApiError => e
puts "API-Fehler #{e.status_code}: #{e.message}"
endFormat-spezifische Beispiele
XRechnung (Deutsche B2G)
ruby
result = client.invoice
.format('xrechnung')
.leitweg_id('04011000-12345-67')
.seller(
name: 'Acme GmbH',
vat_id: 'DE123456789',
email: 'rechnung@acme.de', # Erforderlich
street: 'Hauptstraße 1',
city: 'Berlin',
postal_code: '10115',
country: 'DE'
)
# ... Rest der Rechnung
.generatePeppol
ruby
result = client.invoice
.format('peppol')
.buyer_reference('PO-12345')
.seller(
name: 'Acme Ltd',
vat_id: 'GB123456789',
peppol_id: '0088:1234567890123',
city: 'London', country: 'GB'
)
.buyer(
name: 'Kunde BV',
peppol_id: '0106:NL123456789B01',
city: 'Amsterdam', country: 'NL'
)
.generateFatturaPA (Italien)
ruby
result = client.invoice
.format('fatturapa')
.tipo_documento('TD01')
.seller(
name: 'Acme S.r.l.',
vat_id: 'IT12345678901',
codice_fiscale: '12345678901',
city: 'Milano', country: 'IT'
)
.buyer(
name: 'Cliente S.p.A.',
vat_id: 'IT98765432109',
codice_destinatario: 'ABCDEFG', # oder pec: 'cliente@pec.it'
city: 'Roma', country: 'IT'
)
.add_item(description: 'Consulenza', quantity: 10, unit_price: 100, vat_rate: 22.0)
.generate
# FatturaPA gibt nur XML zurück
result.save('./fattura.xml')Rails-Integration
ruby
# config/initializers/thelawin.rb
Thelawin.configure do |config|
config.api_key = Rails.application.credentials.thelawin_api_key
config.environment = Rails.env.production? ? :production : :preview
end
# In deinem Controller/Service
class InvoiceService
def generate_invoice(order)
Thelawin.client.invoice
.number(order.invoice_number)
.date(order.created_at.to_date)
.seller(company_details)
.buyer(customer_party(order.customer))
.items(order.line_items.map { |li| line_item_attrs(li) })
.generate
end
endQuellcode
github.com/steviee/thelawin-clients/tree/main/ruby
Vollständige Dokumentation: Ruby SDK