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
embedded = formable.signature_requests.create_embedded(
  template_id: template_id,
  signers: [{ email: "jane@example.com", name: "Jane Doe", role: "Client" }],
  test_mode: true
)

signer = embedded["signers"].first
signing = formable.signature_requests.create_signing_url(
  signer["recipientSignatureId"]
)

# Track progress
current = formable.signature_requests.get(embedded["signatureRequestId"])
all_requests = formable.signature_requests.list(
  updated_since: Time.utc(2026, 1, 1)
)
events = formable.signature_requests.get_events(embedded["signatureRequestId"])

# Download the signed document once completed
envelope = formable.signature_requests.get_signed_envelope(
  embedded["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.message}"
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