formable-sdk
Official Python SDK for the Formable API (v1). Covers templates, signature requests, redlining, and billing.
- Sync (
Formable) and async (AsyncFormable) clients - Fully typed requests and responses (
py.typed) - Python 3.9+
Installation
pip install formable-sdk
Usage
import os
from formable import Formable
formable = Formable(api_key=os.environ["FORMABLE_API_KEY"])
Templates
with open("nda.docx", "rb") as f:
result = formable.templates.create(
file=f.read(),
filename="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)
print(edit["editUrl"], edit["expiresAt"])
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"][0]
signing = formable.signature_requests.create_signing_url(
signer["recipientSignatureId"]
)
# Track progress
from datetime import datetime, timezone
current = formable.signature_requests.get(embedded["signatureRequestId"])
all_requests = formable.signature_requests.list(
updated_since=datetime(2026, 1, 1, tzinfo=timezone.utc)
)
events = formable.signature_requests.get_events(embedded["signatureRequestId"])
# Download the signed document once completed
envelope = formable.signature_requests.get_signed_envelope(
embedded["signatureRequestId"]
)
print(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()
print(billing["numberOfRedliningSessions"])
health = formable.health()
Async client
Every method is also available on AsyncFormable with the same signatures.
import asyncio
from formable import AsyncFormable
async def main():
async with AsyncFormable(api_key=os.environ["FORMABLE_API_KEY"]) as formable:
health = await formable.health()
asyncio.run(main())
Error handling
All non-2xx responses raise a FormableError with the server's error message, HTTP status, and parsed response body.
from formable import FormableError
try:
formable.signature_requests.get("missing-id")
except FormableError as error:
print(error.status, error)
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 |
client |
Custom httpx.Client (or httpx.AsyncClient for async). |
Built-in client with 60s timeout |
Development
python3 -m venv .venv
.venv/bin/pip install -e . pytest mypy build
.venv/bin/python -m pytest tests
.venv/bin/python -m mypy src/formable
Publishing
.venv/bin/python -m build
.venv/bin/python -m pip install twine
.venv/bin/python -m twine upload dist/*
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
formable_sdk-0.1.0.tar.gz
(8.8 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file formable_sdk-0.1.0.tar.gz.
File metadata
- Download URL: formable_sdk-0.1.0.tar.gz
- Upload date:
- Size: 8.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32c20e12c98ebb7bcf424ae2333fdb402dfaba9f08c92881ae5b88b7b59c0bc9
|
|
| MD5 |
58b19e040f79a06d36b1edf49284b183
|
|
| BLAKE2b-256 |
fce9c12795cdac737bcc010540d016a5925dfae41f5a022b056c6e2af33cf1ec
|
File details
Details for the file formable_sdk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: formable_sdk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cf6fb0a1078a0258bb51165cd6effa9cbf7098beacd106a258509dedc4af89a7
|
|
| MD5 |
7f4ef15d41d49e50e56318cf9c32ceeb
|
|
| BLAKE2b-256 |
0e15c07e3a62f00e6cc39459c8dc2a1df39cffeb2e549812f476e6190136e7b2
|