Class: Assinafy::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/assinafy/client.rb

Overview

Top-level entry point for the Assinafy Ruby SDK.

A Client owns a single Faraday connection (with shared auth headers, timeouts, and User-Agent) and exposes one resource accessor per documented API surface.

Examples:

Construct from positional args

client = Assinafy::Client.create(ENV['ASSINAFY_API_KEY'], ENV['ASSINAFY_ACCOUNT_ID'])

Construct from a config Hash (e.g. parsed YAML/JSON)

client = Assinafy::Client.from_config(api_key: '...', account_id: '...')

See Also:

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key: nil, token: nil, account_id: nil, base_url: Configuration::DEFAULT_BASE_URL, webhook_secret: nil, timeout: Configuration::DEFAULT_TIMEOUT, logger: nil) ⇒ Client

Returns a new instance of Client.

Examples:

Build a client and reach a resource accessor (no network call)

client = Assinafy::Client.new(api_key: 'example_api_key', account_id: 'account_example')
client.documents #=> #<Assinafy::Resources::DocumentResource ...>

Parameters:

  • api_key (String, nil) (defaults to: nil)

    sent as X-Api-Key

  • token (String, nil) (defaults to: nil)

    legacy session token; sent as Authorization: Bearer ... when no api_key is given

  • account_id (String, nil) (defaults to: nil)

    default workspace ID for account-scoped resources; those methods document their supported per-call overrides

  • base_url (String) (defaults to: Configuration::DEFAULT_BASE_URL)
  • webhook_secret (String, nil) (defaults to: nil)
  • timeout (Integer) (defaults to: Configuration::DEFAULT_TIMEOUT)

    Faraday read/open timeout in seconds

  • logger (Logger, nil) (defaults to: nil)

    receives info-level lifecycle messages



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/assinafy/client.rb', line 56

def initialize(api_key: nil, token: nil, account_id: nil,
               base_url: Configuration::DEFAULT_BASE_URL,
               webhook_secret: nil,
               timeout: Configuration::DEFAULT_TIMEOUT,
               logger: nil)
  config = Configuration.new(
    api_key: api_key, token: token, account_id: ,
    base_url: base_url, webhook_secret: webhook_secret,
    timeout: timeout, logger: logger
  )

  @connection = build_connection(config)
  @logger     = config.logger || NullLogger.new

  @auth             = Resources::AuthResource.new(@connection, nil, @logger)
  @accounts         = Resources::AccountResource.new(@connection, , @logger)
  @users            = Resources::UserResource.new(@connection, nil, @logger)
  @documents        = Resources::DocumentResource.new(@connection, , @logger)
  @signers          = Resources::SignerResource.new(@connection, , @logger)
  @signer_documents = Resources::SignerDocumentResource.new(@connection, nil, @logger)
  @assignments      = Resources::AssignmentResource.new(@connection, , @logger)
  @webhooks         = Resources::WebhookResource.new(@connection, , @logger)
  @templates        = Resources::TemplateResource.new(@connection, , @logger)
  @fields           = Resources::FieldResource.new(@connection, , @logger)
  @tags             = Resources::TagResource.new(@connection, , @logger)
  @webhook_verifier = Support::WebhookVerifier.new(webhook_secret)
end

Instance Attribute Details

#accountsResources::AccountResource (readonly)



21
22
23
# File 'lib/assinafy/client.rb', line 21

def accounts
  @accounts
end

#assignmentsResources::AssignmentResource (readonly)



31
32
33
# File 'lib/assinafy/client.rb', line 31

def assignments
  @assignments
end

#authResources::AuthResource (readonly)



19
20
21
# File 'lib/assinafy/client.rb', line 19

def auth
  @auth
end

#documentsResources::DocumentResource (readonly)



25
26
27
# File 'lib/assinafy/client.rb', line 25

def documents
  @documents
end

#fieldsResources::FieldResource (readonly)



37
38
39
# File 'lib/assinafy/client.rb', line 37

def fields
  @fields
end

#signer_documentsResources::SignerDocumentResource (readonly)



29
30
31
# File 'lib/assinafy/client.rb', line 29

def signer_documents
  @signer_documents
end

#signersResources::SignerResource (readonly)



27
28
29
# File 'lib/assinafy/client.rb', line 27

def signers
  @signers
end

#tagsResources::TagResource (readonly)



39
40
41
# File 'lib/assinafy/client.rb', line 39

def tags
  @tags
end

#templatesResources::TemplateResource (readonly)



35
36
37
# File 'lib/assinafy/client.rb', line 35

def templates
  @templates
end

#usersResources::UserResource (readonly)



23
24
25
# File 'lib/assinafy/client.rb', line 23

def users
  @users
end

#webhook_verifierSupport::WebhookVerifier (readonly)



41
42
43
# File 'lib/assinafy/client.rb', line 41

def webhook_verifier
  @webhook_verifier
end

#webhooksResources::WebhookResource (readonly)



33
34
35
# File 'lib/assinafy/client.rb', line 33

def webhooks
  @webhooks
end

Class Method Details

.create(api_key, account_id, **options) ⇒ Client

Convenience constructor with positional api_key/account_id.

Examples:

Construct with positional credentials and an optional webhook secret

client = Assinafy::Client.create('example_api_key', 'account_example', webhook_secret: 'gateway_secret')
client #=> #<Assinafy::Client ...>

Parameters:

  • api_key (String)
  • account_id (String)
  • options (Hash)

    forwarded to #initialize

Returns:



94
95
96
# File 'lib/assinafy/client.rb', line 94

def self.create(api_key, , **options)
  new(api_key: api_key, account_id: , **options)
end

.from_config(config) ⇒ Client

Build a Client from a Hash (string or symbol keys). Useful for credentials loaded from YAML/JSON.

Examples:

Build from a credentials Hash loaded from YAML/JSON (string or symbol keys both work)

creds  = YAML.load_file('config/assinafy.yml') # { 'api_key' => '...', 'account_id' => '...' }
client = Assinafy::Client.from_config(creds)
client #=> #<Assinafy::Client ...>

Parameters:

  • config (Hash)

Returns:



108
109
110
# File 'lib/assinafy/client.rb', line 108

def self.from_config(config)
  from_hash(config)
end

.from_hash(config) ⇒ Client

Alias of from_config for symmetry with Assinafy::Configuration.from_hash.

Examples:

Build from a symbol-keyed Hash

client = Assinafy::Client.from_hash(api_key: 'example_api_key', account_id: 'account_example')
client #=> #<Assinafy::Client ...>

Parameters:

  • config (Hash)

Returns:



120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/assinafy/client.rb', line 120

def self.from_hash(config)
  cfg = Configuration.from_hash(config)
  new(
    api_key:        cfg.api_key,
    token:          cfg.token,
    account_id:     cfg.,
    base_url:       cfg.base_url,
    webhook_secret: cfg.webhook_secret,
    timeout:        cfg.timeout,
    logger:         cfg.logger
  )
end

Instance Method Details

#faraday_connectionFaraday::Connection

Expose the underlying Faraday connection (for advanced use cases, such as adding middleware or inspecting headers in tests).

Examples:

Inspect the auth header the SDK sends

client = Assinafy::Client.new(api_key: 'example_api_key', account_id: 'account_example')
client.faraday_connection.headers['X-Api-Key'] #=> "example_api_key"

Returns:

  • (Faraday::Connection)


225
226
227
# File 'lib/assinafy/client.rb', line 225

def faraday_connection
  @connection
end

#upload_and_request_signatures(source:, signers:, message: nil, wait_for_ready: true, expires_at: nil, copy_receivers: nil, account_id: nil) ⇒ Hash{Symbol=>Object}

Note:

This helper is not transactional. If a later API call fails, an uploaded document or newly created signer may remain and should be cleaned up by the caller.

High-level helper that bundles the most common workflow: upload PDF → (optionally wait for metadata) → create signers → create a virtual assignment for them.

Examples:

Upload a PDF and request a virtual signature from one signer

result = client.upload_and_request_signatures(
  source:  '/path/to/contract.pdf',
  signers: [{ full_name: 'Example Signer', email: 'signer@example.com' }],
  message: 'Please review and sign'
)

# Under the hood the SDK uploads the file, then POSTs this JSON body to
# POST /documents/{document_id}/assignments (nil optional fields are dropped):
#   {
#     "method": "virtual",
#     "signers": [{ "id": "19e6b92e7895332ed9708535d8c" }],
#     "message": "Please review and sign"
#   }

# Returned (unwrapped) Hash:
result
#=> {
#     document: {
#       "resource" => "document", "id" => "1032009d72b364f377ff270405cc",
#       "account_id" => "account_example", "name" => "contract.pdf",
#       "status" => "metadata_ready",
#       "artifacts" => { "original" => "https://.../download/original", "thumbnail" => "https://..." },
#       "tags" => [], "pages" => [{ "id" => "...", "number" => 1, "height" => 1651, "width" => 1275 }]
#       # ... (see docs for full shape)
#     },
#     assignment: {
#       "resource" => "assignment", "id" => "19e99aa0633e32ac13f845c08db",
#       "sender_email" => "sender@example.com", "method" => "virtual",
#       "expires_at" => nil, "message" => "Please review and sign",
#       "signers" => [{ "id" => "19e6b92e7895332ed9708535d8c", "full_name" => "Example Signer",
#                       "email" => "signer@example.com", "completed" => false, "step" => 1 }],
#       "copy_receivers" => [], "items" => [{ "id" => "103200a43e372db16f48a6f0f2d4", "completed" => false }],
#       "summary" => { "signer_count" => 1, "completed_count" => 0 },
#       "signing_urls" => [{ "signer_id" => "19e6b92e7895332ed9708535d8c", "url" => "https://.../sign/..." }]
#       # ... (see docs for full shape)
#     },
#     signer_ids: ["19e6b92e7895332ed9708535d8c"]
#   }

Parameters:

  • source (String, Hash)
  • signers (Array<Hash>)
  • message (String, nil) (defaults to: nil)
  • wait_for_ready (Boolean) (defaults to: true)

    poll until the document is metadata-ready (default true)

  • expires_at (String, nil) (defaults to: nil)

    ISO 8601 expiration for the assignment

  • copy_receivers (Array<String>, nil) (defaults to: nil)

    signer IDs that only receive copies

  • account_id (String, nil) (defaults to: nil)

    override the client default

Returns:

  • (Hash{Symbol=>Object})

    { document: {Hash}, assignment: {Hash}, signer_ids: [String, ...] } where document is the (unwrapped) document payload, assignment is the (unwrapped) virtual assignment, and signer_ids lists the IDs of the signers created during the workflow.



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/assinafy/client.rb', line 189

def upload_and_request_signatures(source:, signers:, message: nil,
                                  wait_for_ready: true, expires_at: nil,
                                  copy_receivers: nil, account_id: nil)
  unless signers.is_a?(Array) && !signers.empty? && signers.all?(Hash)
    raise ValidationError.new('Signers must be a non-empty Array of Hashes')
  end

  @logger.info("Starting upload and signature workflow for #{signers.length} signer(s)")

  upload_opts = .nil? ? {} : { account_id:  }
  document = @documents.upload(source, upload_opts)
  document = @documents.wait_until_ready(document['id']) if wait_for_ready

  signer_ids = signers.map do |signer|
    created = @signers.create(signer, )
    created['id'] || raise(ApiError.new('Signer created but the API returned no ID', 502, created))
  end

  assignment_payload = { method: 'virtual', signers: signer_ids,
                         message: message, expires_at: expires_at,
                         copy_receivers: copy_receivers }
  assignment = @assignments.create(document['id'], assignment_payload)

  @logger.info("Upload and signature workflow completed for document #{document['id']}")

  { document: document, assignment: assignment, signer_ids: signer_ids }
end