Project

formable

0.0
The project is in a healthy, maintained state
Official Ruby SDK for the Formable API. Covers templates, signature requests, redlining, and billing.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

 Project Readme

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

To publish a new version, see RELEASING.md.