formable

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2026 License: MIT Imports: 12 Imported by: 0

README

formable-go

Official Go SDK for the Formable API (v1). Covers templates, signature requests, redlining, and billing.

  • Typed request and response models
  • Uses the Go standard library (net/http)
  • Context on every method
  • Zero runtime dependencies (Go 1.22+)

Installation

go get github.com/FormableDocs/formable-go

Usage

import (
    "log"
    "os"

    "github.com/FormableDocs/formable-go"
)

client, err := formable.NewClient(os.Getenv("FORMABLE_API_KEY"))
if err != nil {
    log.Fatal(err)
}
Templates
created, err := client.Templates.CreateFromFile(
    ctx,
    "nda.docx",
    []formable.TemplateSignerRole{
        {Name: "Client", Order: 0},
        {Name: "Witness", Order: 1},
    },
)
if err != nil {
    log.Fatal(err)
}

templateID := created.TemplateID

// Mint a fresh edit URL later (expires after 1 day)
edit, err := client.Templates.CreateEditURL(ctx, templateID)
Signature requests
// Formable emails each signer a signing link
request, err := client.SignatureRequests.Create(ctx, &formable.CreateSignatureRequest{
    TemplateID: templateID,
    Signers: []formable.Signer{
        {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, err := client.SignatureRequests.CreateEmbedded(ctx, &formable.CreateSignatureRequest{
    TemplateID: templateID,
    Signers:    []formable.Signer{{Email: "jane@example.com", Name: "Jane Doe", Role: "Client"}},
    TestMode:   true,
})

signer := embedded.Signers[0]
signing, err := client.SignatureRequests.CreateSigningURL(ctx, signer.RecipientSignatureID)

// Track progress
current, err := client.SignatureRequests.Get(ctx, embedded.SignatureRequestID)
all, err := client.SignatureRequests.List(ctx, &formable.ListOptions{
    UpdatedSince: time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC),
})
events, err := client.SignatureRequests.GetEvents(ctx, embedded.SignatureRequestID)

// Download the signed document once completed
envelope, err := client.SignatureRequests.GetSignedEnvelope(ctx, embedded.SignatureRequestID)
Redline requests
created, err := client.RedlineRequests.Create(ctx, &formable.CreateRedlineRequest{
    TemplateID: templateID,
    Members: []formable.RedlineMember{
        {Email: "us@example.com", DisplayName: "John Doe", Role: formable.RedlineMemberRoleDisclosingParty},
        {Email: "them@example.com", DisplayName: "Jane Smith", Role: formable.RedlineMemberRoleReceivingParty},
    },
    Metadata: &formable.RedlineRequestMetadata{Subject: "Mutual NDA"},
})

redlineRequestID := created.RedlineRequestID

// Mint a redline URL for a member (embed in an iframe)
url, err := client.RedlineRequests.CreateURL(ctx, redlineRequestID, "them@example.com")

// Manage members and track progress
_, err = client.RedlineRequests.UpdateMembers(ctx, redlineRequestID, []formable.RedlineMember{
    {Email: "counsel@example.com", DisplayName: "Counsel", Role: formable.RedlineMemberRoleReceivingCounsel},
})
redline, err := client.RedlineRequests.Get(ctx, redlineRequestID)
events, err := client.RedlineRequests.GetEvents(ctx, redlineRequestID)
Billing and health
billing, err := client.Billing(ctx)
sessions := billing.NumberOfRedliningSessions

health, err := client.Health(ctx)

Error handling

All non-2xx responses return a *formable.Error with the server's error message, HTTP status, and parsed response body.

_, err := client.SignatureRequests.Get(ctx, "missing-id")
var apiErr *formable.Error
if errors.As(err, &apiErr) {
    fmt.Fprintf(os.Stderr, "%d %s\n", apiErr.Status, apiErr.Error())
}

Configuration

httpClient := &http.Client{}

client, err := formable.NewClient(
    os.Getenv("FORMABLE_API_KEY"),
    formable.WithBaseURL("https://api.formabledocs.com/v1"),
    formable.WithTimeout(60*time.Second),
    formable.WithHTTPClient(httpClient),
)
Option Description Default
(positional) Your Formable API key (sent as a bearer token). Required. -
WithBaseURL Override the API base URL. https://api.formabledocs.com/v1
WithTimeout Per-request timeout. 60 seconds
WithHTTPClient Custom *http.Client. Not closed by the SDK. Built-in client

Development

go test ./...
go vet ./...

Publishing

Tag a release. Consumers pick it up with go get:

git tag v0.1.0
git push origin v0.1.0
go get github.com/FormableDocs/formable-go@v0.1.0

Documentation

Overview

Package formable is the official Go client for the Formable API (v1).

Create a client with NewClient, then call methods on Templates, SignatureRequests, and RedlineRequests. Every method takes a context.Context as its first argument.

Index

Constants

View Source
const (
	// DefaultBaseURL is the production Formable API (v1).
	DefaultBaseURL = "https://api.formabledocs.com/v1"

	// Version is the SDK version sent in the User-Agent header.
	Version = "0.1.0"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type BillingResponse

type BillingResponse struct {
	NumberOfRedliningSessions int `json:"numberOfRedliningSessions"`
}

BillingResponse is organization billing usage.

type Client

type Client struct {
	Templates         *TemplatesService
	SignatureRequests *SignatureRequestsService
	RedlineRequests   *RedlineRequestsService
	// contains filtered or unexported fields
}

Client is the official Go client for the Formable API (v1).

func NewClient

func NewClient(apiKey string, opts ...Option) (*Client, error)

NewClient creates a Formable API client. apiKey is sent as a bearer token.

func (*Client) Billing

func (c *Client) Billing(ctx context.Context) (*BillingResponse, error)

Billing returns redlining session usage for the authenticated organization.

func (*Client) Health

func (c *Client) Health(ctx context.Context) (*HealthResponse, error)

Health checks whether the Formable API is up.

type CreateRedlineRequest

type CreateRedlineRequest struct {
	TemplateID string                  `json:"templateId"`
	Members    []RedlineMember         `json:"members"`
	TestMode   bool                    `json:"testMode,omitempty"`
	Metadata   *RedlineRequestMetadata `json:"metadata,omitempty"`
}

CreateRedlineRequest is the body for creating a redline request.

type CreateRedlineRequestResponse

type CreateRedlineRequestResponse struct {
	RedlineRequestID string `json:"redlineRequestId"`
	TemplateID       string `json:"templateId"`
}

CreateRedlineRequestResponse is returned after creating a redline request.

type CreateSignatureRequest

type CreateSignatureRequest struct {
	TemplateID string       `json:"templateId"`
	Signers    []Signer     `json:"signers"`
	Sender     *Party       `json:"sender,omitempty"`
	TestMode   bool         `json:"testMode,omitempty"`
	Fields     []FieldValue `json:"fields,omitempty"`
}

CreateSignatureRequest is the body for creating a regular or embedded signature request.

type CreateTemplateResponse

type CreateTemplateResponse struct {
	TemplateID         string                   `json:"templateId"`
	EditTemplateAccess *TemplateEditURLResponse `json:"editTemplateAccess,omitempty"`
}

CreateTemplateResponse is returned after uploading a template.

type Error

type Error struct {
	// Status is the HTTP status code returned by the API.
	Status int
	// Message is the server's error message, when present.
	Message string
	// Body is the parsed response body, when the server returned JSON.
	Body any
}

Error is returned for any non-2xx response from the Formable API.

func (*Error) Error

func (e *Error) Error() string

type EventMetadata

type EventMetadata struct {
	EventID       string `json:"event_id"`
	EventCategory string `json:"event_category"`
	EventType     string `json:"event_type"`
	EventTime     int64  `json:"event_time"`
}

EventMetadata is common webhook-style metadata on an API event.

type FieldValue

type FieldValue struct {
	FieldID string `json:"fieldId"`
	Value   string `json:"value"`
}

FieldValue prefills a template field when creating a signature request.

type HealthResponse

type HealthResponse struct {
	Status    string  `json:"status"`
	Timestamp string  `json:"timestamp"`
	Uptime    float64 `json:"uptime"`
	Version   string  `json:"version,omitempty"`
}

HealthResponse is the API health check payload.

type ListOptions

type ListOptions struct {
	UpdatedSince time.Time
}

ListOptions filters list endpoints. A zero UpdatedSince omits the query parameter.

type Option

type Option func(*clientConfig)

Option configures a Client.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseURL overrides the API base URL.

func WithHTTPClient

func WithHTTPClient(httpClient *http.Client) Option

WithHTTPClient sets a custom HTTP client. The SDK does not close it.

func WithTimeout

func WithTimeout(timeout time.Duration) Option

WithTimeout sets the per-request timeout. Defaults to 60 seconds.

type Party

type Party struct {
	Email string `json:"email"`
	Name  string `json:"name"`
}

Party is an email and display name.

type RedlineMember

type RedlineMember struct {
	Email       string            `json:"email"`
	DisplayName string            `json:"displayName"`
	Role        RedlineMemberRole `json:"role"`
}

RedlineMember is a participant on a redline request.

type RedlineMemberRole

type RedlineMemberRole string

RedlineMemberRole is a participant's role on a redline request.

const (
	RedlineMemberRoleDisclosingParty   RedlineMemberRole = "DisclosingParty"
	RedlineMemberRoleReceivingParty    RedlineMemberRole = "ReceivingParty"
	RedlineMemberRoleDisclosingCounsel RedlineMemberRole = "DisclosingCounsel"
	RedlineMemberRoleReceivingCounsel  RedlineMemberRole = "ReceivingCounsel"
)

type RedlineMembersResponse

type RedlineMembersResponse struct {
	Members []RedlineMember `json:"members"`
}

RedlineMembersResponse is returned after replacing redline members.

type RedlineRequest

type RedlineRequest struct {
	TemplateID   string               `json:"templateId"`
	Status       RedlineRequestStatus `json:"status"`
	Members      []RedlineMember      `json:"members"`
	TestMode     bool                 `json:"testMode"`
	CurrentRound RedlineRoundParty    `json:"currentRound"`
}

RedlineRequest is the current state of a redline request.

type RedlineRequestEvent

type RedlineRequestEvent struct {
	Event     EventMetadata    `json:"event"`
	Redlining RedliningPayload `json:"redlining"`
}

RedlineRequestEvent is one redlining event on a redline request.

type RedlineRequestEventsResponse

type RedlineRequestEventsResponse struct {
	RedlineRequestEvents []RedlineRequestEvent `json:"redlineRequestEvents"`
}

RedlineRequestEventsResponse is the list of events for a redline request.

type RedlineRequestMetadata

type RedlineRequestMetadata struct {
	Subject string `json:"subject,omitempty"`
}

RedlineRequestMetadata is optional metadata attached to a redline request.

type RedlineRequestStatus

type RedlineRequestStatus string

RedlineRequestStatus is the lifecycle status of a redline request.

const (
	RedlineRequestStatusDisclosingPartyDraft           RedlineRequestStatus = "DisclosingPartyDraft"
	RedlineRequestStatusDisclosingPartyRequestedReview RedlineRequestStatus = "DisclosingPartyRequestedReview"
	RedlineRequestStatusDocumentReadyForSigning        RedlineRequestStatus = "DocumentReadyForSigning"
	RedlineRequestStatusReceivingPartyDraft            RedlineRequestStatus = "ReceivingPartyDraft"
	RedlineRequestStatusReceivingPartyOpened           RedlineRequestStatus = "ReceivingPartyOpened"
	RedlineRequestStatusReceivingPartyRequestedReview  RedlineRequestStatus = "ReceivingPartyRequestedReview"
)

type RedlineRequestsService

type RedlineRequestsService struct {
	// contains filtered or unexported fields
}

RedlineRequestsService creates and tracks redline requests.

func (*RedlineRequestsService) Create

Create starts a turn-based redline request from a template.

func (*RedlineRequestsService) CreateURL

func (s *RedlineRequestsService) CreateURL(ctx context.Context, redlineRequestID, memberEmail string) (*RedlineURLResponse, error)

CreateURL mints a redline editor URL for a member.

func (*RedlineRequestsService) Get

func (s *RedlineRequestsService) Get(ctx context.Context, redlineRequestID string) (*RedlineRequest, error)

Get returns a redline request by ID.

func (*RedlineRequestsService) GetEvents

func (s *RedlineRequestsService) GetEvents(ctx context.Context, redlineRequestID string) (*RedlineRequestEventsResponse, error)

GetEvents returns redlining events for a redline request.

func (*RedlineRequestsService) List

List returns redline requests for the authenticated organization.

func (*RedlineRequestsService) UpdateMembers

func (s *RedlineRequestsService) UpdateMembers(ctx context.Context, redlineRequestID string, members []RedlineMember) (*RedlineMembersResponse, error)

UpdateMembers replaces the members on a redline request.

type RedlineRoundParty

type RedlineRoundParty string

RedlineRoundParty is which side currently holds the redline turn.

const (
	RedlineRoundPartyDisclosing RedlineRoundParty = "Disclosing"
	RedlineRoundPartyReceiving  RedlineRoundParty = "Receiving"
)

type RedlineURLResponse

type RedlineURLResponse struct {
	RedlineURL string `json:"redlineUrl"`
	ExpiresAt  string `json:"expiresAt"`
}

RedlineURLResponse is a time-limited embedded redline editor URL.

type RedliningPayload

type RedliningPayload struct {
	RedlineRequestID     string `json:"redline_request_id"`
	RedlineMemberRole    string `json:"redline_member_role,omitempty"`
	RedlineEditInsertion string `json:"redline_edit_insertion,omitempty"`
	RedlineEditDeletion  string `json:"redline_edit_deletion,omitempty"`
	Content              string `json:"content,omitempty"`
	ChangeType           string `json:"change_type,omitempty"`
	CommentAdded         string `json:"comment_added,omitempty"`
	Message              string `json:"message,omitempty"`
	AuthorEmail          string `json:"author_email,omitempty"`
}

RedliningPayload is the redlining-specific portion of a redline request event.

type SignatureRequest

type SignatureRequest struct {
	SignatureRequestID string                   `json:"signatureRequestId"`
	TemplateID         string                   `json:"templateId"`
	Signers            []SignatureRequestSigner `json:"signers"`
	Sender             Party                    `json:"sender"`
	Status             SignatureRequestStatus   `json:"status"`
	TestMode           bool                     `json:"testMode"`
	Fields             []SignatureRequestField  `json:"fields,omitempty"`
}

SignatureRequest is a v1 signature request.

type SignatureRequestEvent

type SignatureRequestEvent struct {
	Event   EventMetadata  `json:"event"`
	Signing SigningPayload `json:"signing"`
}

SignatureRequestEvent is one signing event on a signature request.

type SignatureRequestEventsResponse

type SignatureRequestEventsResponse struct {
	SignatureRequestEvents []SignatureRequestEvent `json:"signatureRequestEvents"`
}

SignatureRequestEventsResponse is the list of events for a signature request.

type SignatureRequestField

type SignatureRequestField struct {
	FieldID              string                    `json:"fieldId"`
	Type                 SignatureRequestFieldType `json:"type"`
	Required             bool                      `json:"required"`
	Filled               bool                      `json:"filled"`
	RecipientSignatureID string                    `json:"recipientSignatureId,omitempty"`
	Value                any                       `json:"value,omitempty"`
	Label                string                    `json:"label,omitempty"`
	Role                 string                    `json:"role,omitempty"`
	Unit                 string                    `json:"unit,omitempty"`
	SignedAt             string                    `json:"signedAt,omitempty"`
}

SignatureRequestField is a field on a signature request.

type SignatureRequestFieldType

type SignatureRequestFieldType string

SignatureRequestFieldType is a field type on a signature request.

const (
	SignatureRequestFieldTypeText      SignatureRequestFieldType = "text"
	SignatureRequestFieldTypeParagraph SignatureRequestFieldType = "paragraph"
	SignatureRequestFieldTypeCheckbox  SignatureRequestFieldType = "checkbox"
	SignatureRequestFieldTypeDate      SignatureRequestFieldType = "date"
	SignatureRequestFieldTypeAmount    SignatureRequestFieldType = "amount"
	SignatureRequestFieldTypeDropdown  SignatureRequestFieldType = "dropdown"
	SignatureRequestFieldTypeSignature SignatureRequestFieldType = "signature"
)

type SignatureRequestListItem

type SignatureRequestListItem struct {
	SignatureRequestID string                 `json:"signatureRequestId"`
	TemplateID         string                 `json:"templateId"`
	Signer             Party                  `json:"signer"`
	Sender             Party                  `json:"sender"`
	Status             SignatureRequestStatus `json:"status"`
	TestMode           bool                   `json:"testMode"`
}

SignatureRequestListItem is a row from listing signature requests.

type SignatureRequestSigner

type SignatureRequestSigner struct {
	Email                string `json:"email"`
	Name                 string `json:"name"`
	RecipientSignatureID string `json:"recipientSignatureId"`
}

SignatureRequestSigner is a signer on a created signature request.

type SignatureRequestStatus

type SignatureRequestStatus string

SignatureRequestStatus is the lifecycle status of a signature request.

const (
	SignatureRequestStatusCreated   SignatureRequestStatus = "Created"
	SignatureRequestStatusCompleted SignatureRequestStatus = "Completed"
	SignatureRequestStatusExpired   SignatureRequestStatus = "Expired"
)

type SignatureRequestsService

type SignatureRequestsService struct {
	// contains filtered or unexported fields
}

SignatureRequestsService creates and tracks signature requests.

func (*SignatureRequestsService) Create

Create sends a template for signing. Formable emails each signer a link.

func (*SignatureRequestsService) CreateEmbedded

CreateEmbedded starts an embedded signature request. Mint a signing URL for each signer yourself.

func (*SignatureRequestsService) CreateSigningURL

func (s *SignatureRequestsService) CreateSigningURL(ctx context.Context, recipientSignatureID string) (*SigningURLResponse, error)

CreateSigningURL mints a signing URL for an embedded recipient signature.

func (*SignatureRequestsService) Get

func (s *SignatureRequestsService) Get(ctx context.Context, signatureRequestID string) (*SignatureRequest, error)

Get returns a signature request by ID.

func (*SignatureRequestsService) GetEvents

func (s *SignatureRequestsService) GetEvents(ctx context.Context, signatureRequestID string) (*SignatureRequestEventsResponse, error)

GetEvents returns signing events for a signature request.

func (*SignatureRequestsService) GetSignedEnvelope

func (s *SignatureRequestsService) GetSignedEnvelope(ctx context.Context, signatureRequestID string) (*SignedEnvelopeResponse, error)

GetSignedEnvelope returns a presigned URL for the completed signed document.

func (*SignatureRequestsService) List

List returns signature requests for the authenticated organization.

type SignedEnvelopeResponse

type SignedEnvelopeResponse struct {
	SignedEnvelopePresignedURL string `json:"signedEnvelopePresignedUrl"`
}

SignedEnvelopeResponse is a presigned URL for the completed document.

type Signer

type Signer struct {
	Email string `json:"email"`
	Name  string `json:"name"`
	Role  string `json:"role,omitempty"`
}

Signer is a recipient on a create-signature-request call.

type SigningPayload

type SigningPayload struct {
	SignatureRequestID   string `json:"signature_request_id"`
	RecipientSignatureID string `json:"recipient_signature_id,omitempty"`
}

SigningPayload is the signing-specific portion of a signature request event.

type SigningURLResponse

type SigningURLResponse struct {
	SigningURL string `json:"signingUrl"`
	ExpiresAt  string `json:"expiresAt"`
}

SigningURLResponse is a time-limited embedded signing URL.

type TemplateEditURLResponse

type TemplateEditURLResponse struct {
	EditURL   string `json:"editUrl"`
	ExpiresAt string `json:"expiresAt"`
}

TemplateEditURLResponse is a time-limited URL to the template editor.

type TemplateSignerRole

type TemplateSignerRole struct {
	Name  string `json:"name"`
	Order int    `json:"order"`
}

TemplateSignerRole is a named signing order on a template.

type TemplatesService

type TemplatesService struct {
	// contains filtered or unexported fields
}

TemplatesService uploads templates and mints template edit URLs.

func (*TemplatesService) Create

func (s *TemplatesService) Create(ctx context.Context, filename string, file []byte, signerRoles []TemplateSignerRole) (*CreateTemplateResponse, error)

Create uploads a document as a reusable template.

func (*TemplatesService) CreateEditURL

func (s *TemplatesService) CreateEditURL(ctx context.Context, templateID string) (*TemplateEditURLResponse, error)

CreateEditURL mints a template editor URL that expires after one day.

func (*TemplatesService) CreateFromFile

func (s *TemplatesService) CreateFromFile(ctx context.Context, path string, signerRoles []TemplateSignerRole) (*CreateTemplateResponse, error)

CreateFromFile reads path and uploads it as a template. The filename is the base name of path.

func (*TemplatesService) CreateFromReader

func (s *TemplatesService) CreateFromReader(ctx context.Context, filename string, r io.Reader, signerRoles []TemplateSignerRole) (*CreateTemplateResponse, error)

CreateFromReader reads r and uploads it as a template.

Directories

Path Synopsis
examples
quickstart command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL