formable-ruby
Official Ruby SDK for the Formable API (v1). Covers templates, signature requests, redlining, and billing.
- Faraday HTTP client (injectable)
- Keyword arguments and snake_case method names
- Ruby 3.1+
Installation
# Gemfile
gem "formable"
bundle add formable
# or
gem install formable
Usage
require "formable"
formable = Formable.new(api_key: ENV.fetch("FORMABLE_API_KEY"))
Templates
result = formable.templates.create(
file: "nda.docx",
signer_roles: [
{ name: "Client", order: 0 },
{ name: "Witness", order: 1 }
]
)
template_id = result["templateId"]
# Mint a fresh edit URL later (expires after 1 day)
edit = formable.templates.create_edit_url(template_id)
puts edit["editUrl"], edit["expiresAt"]
file accepts a path, binary string, or IO. Pass filename: when file is not a path.
Signature requests
# Formable emails each signer a signing link
request = formable.signature_requests.create(
template_id: template_id,
signers: [
{ email: "jane@example.com", name: "Jane Doe", role: "Client" },
{ email: "bob@example.com", name: "Bob Smith", role: "Witness" }
]
)
# Embedded flow: mint signing URLs to embed in an iframe yourself
= formable.signature_requests.(
template_id: template_id,
signers: [{ email: "jane@example.com", name: "Jane Doe", role: "Client" }],
test_mode: true
)
signer = ["signers"].first
signing = formable.signature_requests.create_signing_url(
signer["recipientSignatureId"]
)
# Track progress
current = formable.signature_requests.get(["signatureRequestId"])
all_requests = formable.signature_requests.list(
updated_since: Time.utc(2026, 1, 1)
)
events = formable.signature_requests.get_events(["signatureRequestId"])
# Download the signed document once completed
envelope = formable.signature_requests.get_signed_envelope(
["signatureRequestId"]
)
puts envelope["signedEnvelopePresignedUrl"]
Redline requests
created = formable.redline_requests.create(
template_id: template_id,
members: [
{ email: "us@example.com", display_name: "John Doe", role: "DisclosingParty" },
{ email: "them@example.com", display_name: "Jane Smith", role: "ReceivingParty" }
],
metadata: { subject: "Mutual NDA" }
)
redline_request_id = created["redlineRequestId"]
# Mint a redline URL for a member (embed in an iframe)
url = formable.redline_requests.create_url(redline_request_id, "them@example.com")
# Manage members and track progress
formable.redline_requests.update_members(
redline_request_id,
[{ email: "counsel@example.com", display_name: "Counsel", role: "ReceivingCounsel" }]
)
redline = formable.redline_requests.get(redline_request_id)
events = formable.redline_requests.get_events(redline_request_id)
Billing and health
billing = formable.billing
puts billing["numberOfRedliningSessions"]
health = formable.health
Error handling
All non-2xx responses raise a Formable::Error with the server's error message, HTTP status, and parsed response body.
begin
formable.signature_requests.get("missing-id")
rescue Formable::Error => error
warn "#{error.status} #{error.}"
end
Configuration
| Option | Description | Default |
|---|---|---|
api_key |
Your Formable API key (sent as a bearer token). Required. | - |
base_url |
Override the API base URL. | https://api.formabledocs.com/v1 |
timeout |
Per-request timeout in seconds. | 60 |
connection |
Custom Faraday::Connection. |
Built-in client with 60s timeout |
Request hashes accept snake_case keys (template_id, display_name, field_id). Responses use the API's camelCase field names (templateId, displayName).
Development
bundle install
bundle exec rake test
Publishing
gem build formable.gemspec
gem push formable-*.gem