boldsign 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f0a4d128418d45a484979b044ce83a9e868ef1a142145962ec0580b0f34f4e20
4
+ data.tar.gz: 4ee136cc02d3020b4beb1e70d614929de07f0f64e7965d8e0742a3e74cb0b893
5
+ SHA512:
6
+ metadata.gz: 486cb527ac17cef2ddcf9505a5a2bfe59b3736ee75d9e9b8778344c16a8b6c0e5795d17f5fa7d739fb87f6dc70e1e353fea13929e4303ab8abf1c08adf66e792
7
+ data.tar.gz: 79edff344004bd59f868a44b6812c1c16bfa922823d0a16eaf28be54f970714b75c16d19be411e6ea175d37b4de8e7ab7bcc30b75da592ade64c49a7afbd9a12
data/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] — 2026-05-22
11
+
12
+ ### Added
13
+ - Initial release.
14
+ - `Boldsign::Client` covering all 84 endpoints of the BoldSign v1 REST API
15
+ across 11 resource groups: documents, templates, contacts, contact groups,
16
+ custom fields, sender identities, brands, teams, users, identity
17
+ verification, and plan info.
18
+ - Region support (`:us`, `:eu`, `:ca`, `:au`) plus explicit base-URL override.
19
+ - Typed error hierarchy mapped from HTTP status codes.
20
+ - YARD documentation for the public API.
21
+ - 100% line and branch test coverage enforced via SimpleCov.
22
+ - GitHub Actions CI on Ruby 3.4 and 4.0.
23
+
24
+ [Unreleased]: https://github.com/kleinjm/boldsign-ruby/compare/v0.1.0...HEAD
25
+ [0.1.0]: https://github.com/kleinjm/boldsign-ruby/releases/tag/v0.1.0
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 James Klein
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # boldsign-ruby
2
+
3
+ [![CI](https://github.com/kleinjm/boldsign-ruby/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/kleinjm/boldsign-ruby/actions/workflows/ci.yml)
4
+ [![API docs](https://img.shields.io/badge/docs-rubydoc.info-blue.svg)](https://rubydoc.info/github/kleinjm/boldsign-ruby/main)
5
+
6
+ A Ruby client for the [BoldSign](https://developers.boldsign.com/) e-signature API.
7
+
8
+ Wraps every public endpoint of the BoldSign v1 REST API: documents, templates,
9
+ contacts, contact groups, custom fields, sender identities, brands, teams,
10
+ users, identity verification, and plan info.
11
+
12
+ ## Installation
13
+
14
+ ```ruby
15
+ gem "boldsign"
16
+ ```
17
+
18
+ ## Configuration
19
+
20
+ ```ruby
21
+ Boldsign.configure do |c|
22
+ c.api_key = ENV["BOLDSIGN_API_KEY"]
23
+ c.region = :us # :us, :eu, :ca, :au (or set c.base_url directly)
24
+ end
25
+ ```
26
+
27
+ Or instantiate a client directly:
28
+
29
+ ```ruby
30
+ client = Boldsign::Client.new(api_key: "…", region: :us)
31
+ ```
32
+
33
+ Region base URLs:
34
+
35
+ | Region | URL |
36
+ | ------ | --- |
37
+ | `:us` | `https://api.boldsign.com` |
38
+ | `:eu` | `https://api-eu.boldsign.com` |
39
+ | `:ca` | `https://api-ca.boldsign.com` |
40
+ | `:au` | `https://api-au.boldsign.com` |
41
+
42
+ ## Usage
43
+
44
+ ```ruby
45
+ client = Boldsign.client
46
+
47
+ # Send a document
48
+ client.documents.send_document(
49
+ title: "NDA",
50
+ signers: [{ name: "Jane Doe", emailAddress: "jane@example.com", signerOrder: 1 }],
51
+ files: [...] # see BoldSign docs for the full schema
52
+ )
53
+
54
+ # List documents
55
+ client.documents.list(page: 1, pageSize: 50)
56
+
57
+ # Properties / download
58
+ client.documents.properties("DOCUMENT_ID")
59
+ File.binwrite("signed.pdf", client.documents.download("DOCUMENT_ID"))
60
+
61
+ # Templates
62
+ client.templates.list
63
+ client.templates.send_template("TEMPLATE_ID", roles: [...])
64
+
65
+ # Contacts / contact groups
66
+ client.contacts.create(contacts: [{ name: "Jane", emailAddress: "jane@example.com" }])
67
+ client.contact_groups.list
68
+
69
+ # Users & teams
70
+ client.users.list
71
+ client.teams.create(teamName: "Sales")
72
+
73
+ # Brands
74
+ client.brand.list
75
+
76
+ # Plan
77
+ client.plan.api_credits_count
78
+ ```
79
+
80
+ ## Resources & methods
81
+
82
+ Each resource on `Boldsign::Client` maps to a group of BoldSign endpoints:
83
+
84
+ | Accessor | Methods |
85
+ | -------- | ------- |
86
+ | `client.documents` | `list`, `team_list`, `behalf_list`, `properties`, `send_document`, `draft_send`, `edit`, `cancel_editing`, `create_embedded_request_url`, `create_embedded_edit_url`, `get_embedded_sign_link`, `download`, `download_attachment`, `download_audit_log`, `revoke`, `remind`, `delete`, `extend_expiry`, `change_access_code`, `change_recipient`, `add_tags`, `delete_tags`, `add_authentication`, `remove_authentication`, `prefill_fields` |
87
+ | `client.templates` | `list`, `properties`, `download`, `create`, `edit`, `delete`, `send_template`, `merge_and_send`, `create_embedded_template_url`, `get_embedded_template_edit_url`, `create_embedded_request_url`, `merge_create_embedded_request_url`, `create_embedded_preview_url`, `add_tags`, `delete_tags` |
88
+ | `client.contacts` | `list`, `get`, `create`, `update`, `delete` |
89
+ | `client.contact_groups` | `list`, `get`, `create`, `update`, `delete` |
90
+ | `client.custom_fields` | `list`, `create`, `edit`, `delete`, `create_embedded_url` |
91
+ | `client.sender_identities` | `list`, `properties`, `create`, `update`, `delete`, `resend_invitation`, `rerequest` |
92
+ | `client.brand` | `list`, `get`, `create`, `edit`, `delete`, `reset_default` |
93
+ | `client.teams` | `list`, `get`, `create`, `update` |
94
+ | `client.users` | `list`, `get`, `create`, `update`, `update_metadata`, `change_team`, `resend_invitation`, `cancel_invitation` |
95
+ | `client.identity_verification` | `report`, `image`, `create_embedded_url` |
96
+ | `client.plan` | `api_credits_count` |
97
+
98
+ All methods accept Ruby hashes (with camelCase keys matching the BoldSign API)
99
+ and return parsed JSON. Binary endpoints (`download*`) return raw bytes.
100
+
101
+ ## Errors
102
+
103
+ HTTP errors raise a typed subclass of `Boldsign::Error`:
104
+
105
+ `BadRequestError` (400), `AuthenticationError` (401), `ForbiddenError` (403),
106
+ `NotFoundError` (404), `UnprocessableEntityError` (422), `RateLimitError` (429),
107
+ `ServerError` (5xx). Each carries `#status`, `#body`, and `#response`.
108
+
109
+ ## Documentation
110
+
111
+ Full YARD API documentation is auto-built and hosted at
112
+ [rubydoc.info/github/kleinjm/boldsign-ruby/main](https://rubydoc.info/github/kleinjm/boldsign-ruby/main).
113
+
114
+ To generate locally:
115
+
116
+ ```sh
117
+ bundle exec yard doc
118
+ open doc/index.html
119
+ ```
120
+
121
+ ## Development
122
+
123
+ ```sh
124
+ bundle install
125
+ bundle exec rspec # run tests (enforces 100% line + branch coverage)
126
+ bundle exec yard doc # build local API docs to ./doc
127
+ ```
128
+
129
+ ## License
130
+
131
+ MIT
data/boldsign.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ require_relative "lib/boldsign/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "boldsign"
5
+ spec.version = Boldsign::VERSION
6
+ spec.authors = ["James Klein"]
7
+ spec.email = ["kleinjm007@gmail.com"]
8
+
9
+ spec.summary = "Ruby client for the BoldSign e-signature API"
10
+ spec.description = "A Ruby wrapper for the BoldSign REST API (documents, templates, " \
11
+ "contacts, teams, brands, webhooks, and more)."
12
+ spec.homepage = "https://github.com/kleinjm/boldsign-ruby"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 3.0"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = spec.homepage
18
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
19
+ spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
20
+ spec.metadata["documentation_uri"] = "https://rubydoc.info/gems/boldsign"
21
+ spec.metadata["rubygems_mfa_required"] = "true"
22
+
23
+ spec.files = Dir["lib/**/*.rb", "README.md", "CHANGELOG.md", "LICENSE.txt", "boldsign.gemspec"]
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_dependency "faraday", ">= 2.0"
27
+ spec.add_dependency "faraday-multipart", ">= 1.0"
28
+
29
+ spec.add_development_dependency "rake", "~> 13.0"
30
+ spec.add_development_dependency "rspec", "~> 3.12"
31
+ spec.add_development_dependency "webmock", "~> 3.19"
32
+ end
@@ -0,0 +1,171 @@
1
+ module Boldsign
2
+ # HTTP client for the BoldSign REST API.
3
+ #
4
+ # Holds API credentials and exposes one accessor per resource group
5
+ # (`documents`, `templates`, `contacts`, …). Each accessor returns a memoized
6
+ # resource object whose methods wrap individual endpoints.
7
+ #
8
+ # Low-level verb methods ({#get}, {#post}, {#put}, {#patch}, {#delete},
9
+ # {#download}) are also available for hitting any endpoint directly.
10
+ #
11
+ # @example
12
+ # client = Boldsign::Client.new(api_key: ENV["BOLDSIGN_API_KEY"], region: :us)
13
+ # client.documents.send_document(title: "NDA", signers: [...])
14
+ class Client
15
+ # Default region (US).
16
+ DEFAULT_BASE_URL = "https://api.boldsign.com".freeze
17
+
18
+ # User-Agent header value sent on every request.
19
+ USER_AGENT = "boldsign-ruby/#{Boldsign::VERSION}".freeze
20
+
21
+ # @return [String] the API key in use.
22
+ attr_reader :api_key
23
+
24
+ # @return [String] the resolved base URL (region or explicit override).
25
+ attr_reader :base_url
26
+
27
+ # @param api_key [String, nil] BoldSign API key. Falls back to `ENV["BOLDSIGN_API_KEY"]`.
28
+ # @param region [Symbol, nil] One of `:us`, `:eu`, `:ca`, `:au`. Ignored if `base_url` is given.
29
+ # @param base_url [String, nil] Explicit base URL override.
30
+ # @param adapter [Symbol] Faraday adapter (defaults to `Faraday.default_adapter`).
31
+ # @param logger [Logger, nil] Optional logger; when present, Faraday's logger middleware is enabled.
32
+ # @raise [ConfigurationError] when no API key is available.
33
+ def initialize(api_key: nil, region: nil, base_url: nil, adapter: Faraday.default_adapter, logger: nil)
34
+ @api_key = api_key || ENV["BOLDSIGN_API_KEY"]
35
+ raise ConfigurationError, "Missing BoldSign API key" if @api_key.nil? || @api_key.empty?
36
+
37
+ @base_url = base_url || Boldsign::REGIONS[region&.to_sym] || DEFAULT_BASE_URL
38
+ @adapter = adapter
39
+ @logger = logger
40
+ end
41
+
42
+ # @return [Resources::Brand]
43
+ def brand; @brand ||= Resources::Brand.new(self); end
44
+ # @return [Resources::Contact]
45
+ def contacts; @contacts ||= Resources::Contact.new(self); end
46
+ # @return [Resources::ContactGroup]
47
+ def contact_groups; @contact_groups ||= Resources::ContactGroup.new(self); end
48
+ # @return [Resources::CustomField]
49
+ def custom_fields; @custom_fields ||= Resources::CustomField.new(self); end
50
+ # @return [Resources::Document]
51
+ def documents; @documents ||= Resources::Document.new(self); end
52
+ # @return [Resources::IdentityVerification]
53
+ def identity_verification; @identity_verification ||= Resources::IdentityVerification.new(self); end
54
+ # @return [Resources::Plan]
55
+ def plan; @plan ||= Resources::Plan.new(self); end
56
+ # @return [Resources::SenderIdentity]
57
+ def sender_identities; @sender_identities ||= Resources::SenderIdentity.new(self); end
58
+ # @return [Resources::Team]
59
+ def teams; @teams ||= Resources::Team.new(self); end
60
+ # @return [Resources::Template]
61
+ def templates; @templates ||= Resources::Template.new(self); end
62
+ # @return [Resources::User]
63
+ def users; @users ||= Resources::User.new(self); end
64
+
65
+ # Issue a GET request.
66
+ # @param path [String] request path (e.g. `/v1/document/list`).
67
+ # @param params [Hash] query string parameters.
68
+ # @return [Hash, Array, String, nil] parsed JSON body, or raw body for non-JSON responses.
69
+ # @raise [Error] on any non-success HTTP status.
70
+ def get(path, params = {})
71
+ request(:get, path, params: params)
72
+ end
73
+
74
+ # Issue a POST request.
75
+ # @param path [String] request path.
76
+ # @param body [Hash, String, nil] request body. Hashes are JSON-encoded;
77
+ # pre-serialized JSON strings are sent as-is.
78
+ # @param params [Hash] query string parameters.
79
+ # @param multipart [Boolean] when `true`, body is sent as `multipart/form-data`
80
+ # (include `Faraday::Multipart::FilePart` values to upload files).
81
+ # @return [Hash, Array, String, nil]
82
+ # @raise [Error] on any non-success HTTP status.
83
+ def post(path, body: nil, params: {}, multipart: false)
84
+ request(:post, path, body: body, params: params, multipart: multipart)
85
+ end
86
+
87
+ # Issue a PUT request. See {#post} for parameter semantics.
88
+ def put(path, body: nil, params: {})
89
+ request(:put, path, body: body, params: params)
90
+ end
91
+
92
+ # Issue a PATCH request. See {#post} for parameter semantics.
93
+ def patch(path, body: nil, params: {})
94
+ request(:patch, path, body: body, params: params)
95
+ end
96
+
97
+ # Issue a DELETE request.
98
+ # @param path [String] request path.
99
+ # @param params [Hash] query string parameters.
100
+ def delete(path, params = {})
101
+ request(:delete, path, params: params)
102
+ end
103
+
104
+ # Issue a GET request and return the raw response body without JSON parsing.
105
+ # Use for binary endpoints (downloads, audit logs, attachments).
106
+ # @param path [String] request path.
107
+ # @param params [Hash] query string parameters.
108
+ # @return [String] raw response bytes.
109
+ # @raise [Error] on any non-success HTTP status.
110
+ def download(path, params = {})
111
+ response = connection.get(path) do |req|
112
+ req.params.update(params) if params && !params.empty?
113
+ end
114
+ handle_errors(response)
115
+ response.body
116
+ end
117
+
118
+ private
119
+
120
+ def request(method, path, body: nil, params: {}, multipart: false)
121
+ response = connection(multipart: multipart).public_send(method, path) do |req|
122
+ req.params.update(params) if params && !params.empty?
123
+ if body
124
+ if multipart
125
+ req.body = body
126
+ else
127
+ req.headers["Content-Type"] = "application/json"
128
+ req.body = body.is_a?(String) ? body : JSON.generate(body)
129
+ end
130
+ end
131
+ end
132
+ handle_errors(response)
133
+ parse_body(response)
134
+ end
135
+
136
+ def connection(multipart: false)
137
+ Faraday.new(url: @base_url) do |f|
138
+ f.request :multipart if multipart
139
+ f.request :url_encoded
140
+ f.headers["X-API-KEY"] = @api_key
141
+ f.headers["Accept"] = "application/json"
142
+ f.headers["User-Agent"] = USER_AGENT
143
+ f.response :logger, @logger if @logger
144
+ f.adapter @adapter
145
+ end
146
+ end
147
+
148
+ def parse_body(response)
149
+ return nil if response.body.nil? || response.body.empty?
150
+ content_type = response.headers["content-type"].to_s
151
+ return response.body unless content_type.include?("json")
152
+ JSON.parse(response.body)
153
+ rescue JSON::ParserError
154
+ response.body
155
+ end
156
+
157
+ def handle_errors(response)
158
+ return if response.success?
159
+
160
+ body = begin
161
+ JSON.parse(response.body)
162
+ rescue StandardError
163
+ response.body
164
+ end
165
+ message = body.is_a?(Hash) ? (body["message"] || body["error"] || body.to_s) : body.to_s
166
+ klass = ERROR_MAP[response.status] || (response.status >= 500 ? ServerError : Error)
167
+ raise klass.new("BoldSign API error (#{response.status}): #{message}",
168
+ status: response.status, body: body, response: response)
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,46 @@
1
+ module Boldsign
2
+ # Base class for all errors raised by this gem.
3
+ # HTTP failures raise a typed subclass; carry the status code, parsed body, and Faraday response.
4
+ class Error < StandardError
5
+ # @return [Integer, nil] HTTP status code, when the error originated from a response.
6
+ attr_reader :status
7
+ # @return [Hash, String, nil] parsed response body (JSON Hash) or raw body string.
8
+ attr_reader :body
9
+ # @return [Faraday::Response, nil] underlying Faraday response.
10
+ attr_reader :response
11
+
12
+ def initialize(message = nil, status: nil, body: nil, response: nil)
13
+ super(message)
14
+ @status = status
15
+ @body = body
16
+ @response = response
17
+ end
18
+ end
19
+
20
+ # Raised when the gem is misconfigured (e.g. missing API key).
21
+ class ConfigurationError < Error; end
22
+ # HTTP 400.
23
+ class BadRequestError < Error; end
24
+ # HTTP 401.
25
+ class AuthenticationError < Error; end
26
+ # HTTP 403.
27
+ class ForbiddenError < Error; end
28
+ # HTTP 404.
29
+ class NotFoundError < Error; end
30
+ # HTTP 422.
31
+ class UnprocessableEntityError < Error; end
32
+ # HTTP 429.
33
+ class RateLimitError < Error; end
34
+ # HTTP 5xx.
35
+ class ServerError < Error; end
36
+
37
+ # Maps HTTP status codes to {Error} subclasses.
38
+ ERROR_MAP = {
39
+ 400 => BadRequestError,
40
+ 401 => AuthenticationError,
41
+ 403 => ForbiddenError,
42
+ 404 => NotFoundError,
43
+ 422 => UnprocessableEntityError,
44
+ 429 => RateLimitError
45
+ }.freeze
46
+ end
@@ -0,0 +1,17 @@
1
+ module Boldsign
2
+ # Base class for all resource wrappers. Holds a reference to the {Client}
3
+ # instance whose HTTP verb methods the resource methods delegate to.
4
+ class Resource
5
+ # @param client [Client]
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+ end
10
+
11
+ # Namespace for endpoint-group resource classes. Each resource is exposed as
12
+ # an accessor on {Client} (e.g. {Client#documents} → {Resources::Document}).
13
+ #
14
+ # @see https://developers.boldsign.com/ BoldSign API reference
15
+ module Resources
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Boldsign
2
+ module Resources
3
+ # Brand-customization endpoints (`/v1/brand/*`).
4
+ # @see https://developers.boldsign.com/branding
5
+ class Brand < Resource
6
+ def list(**params); @client.get("/v1/brand/list", params); end
7
+ def get(brand_id); @client.get("/v1/brand/get", brandId: brand_id); end
8
+ def create(body, **params); @client.post("/v1/brand/create", body: body, params: params); end
9
+ def edit(brand_id, body); @client.post("/v1/brand/edit", body: body, params: { brandId: brand_id }); end
10
+ def delete(brand_id); @client.delete("/v1/brand/delete", brandId: brand_id); end
11
+ def reset_default(brand_id); @client.post("/v1/brand/resetdefault", params: { brandId: brand_id }); end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module Boldsign
2
+ module Resources
3
+ # Contact-book endpoints (`/v1/contacts/*`).
4
+ # @see https://developers.boldsign.com/contacts
5
+ class Contact < Resource
6
+ def list(**params); @client.get("/v1/contacts/list", params); end
7
+ def get(contact_id); @client.get("/v1/contacts/get", contactId: contact_id); end
8
+ def create(body); @client.post("/v1/contacts/create", body: body); end
9
+ def update(body, **params); @client.put("/v1/contacts/update", body: body, params: params); end
10
+ def delete(contact_id); @client.delete("/v1/contacts/delete", contactId: contact_id); end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Boldsign
2
+ module Resources
3
+ # Contact-group endpoints (`/v1/contactGroups/*`).
4
+ class ContactGroup < Resource
5
+ def list(**params); @client.get("/v1/contactGroups/list", params); end
6
+ def get(group_id); @client.get("/v1/contactGroups/get", groupId: group_id); end
7
+ def create(body); @client.post("/v1/contactGroups/create", body: body); end
8
+ def update(body, **params); @client.put("/v1/contactGroups/update", body: body, params: params); end
9
+ def delete(group_id); @client.delete("/v1/contactGroups/delete", groupId: group_id); end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Boldsign
2
+ module Resources
3
+ # Reusable custom-field endpoints (`/v1/customField/*`).
4
+ class CustomField < Resource
5
+ def list(**params); @client.get("/v1/customField/list", params); end
6
+ def create(body); @client.post("/v1/customField/create", body: body); end
7
+ def edit(body, **params); @client.post("/v1/customField/edit", body: body, params: params); end
8
+ def delete(**params); @client.delete("/v1/customField/delete", params); end
9
+ def create_embedded_url(body); @client.post("/v1/customField/createEmbeddedCustomFieldUrl", body: body); end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,51 @@
1
+ module Boldsign
2
+ module Resources
3
+ # Document endpoints (`/v1/document/*`) — the bulk of the BoldSign API:
4
+ # sending, listing, downloading, editing, reminding, authenticating, tagging,
5
+ # and embedded signing flows.
6
+ #
7
+ # @example Send a document
8
+ # client.documents.send_document(
9
+ # title: "NDA",
10
+ # signers: [{ name: "Jane", emailAddress: "jane@example.com", signerOrder: 1 }],
11
+ # files: [...]
12
+ # )
13
+ #
14
+ # @see https://developers.boldsign.com/documents
15
+ class Document < Resource
16
+ def list(**params); @client.get("/v1/document/list", params); end
17
+ def team_list(**params); @client.get("/v1/document/teamlist", params); end
18
+ def behalf_list(**params); @client.get("/v1/document/behalfList", params); end
19
+ def properties(document_id); @client.get("/v1/document/properties", documentId: document_id); end
20
+
21
+ def send_document(body); @client.post("/v1/document/send", body: body); end
22
+ def draft_send(body); @client.post("/v1/document/draftSend", body: body); end
23
+ def edit(document_id, body); @client.put("/v1/document/edit", body: body, params: { documentId: document_id }); end
24
+ def cancel_editing(document_id); @client.post("/v1/document/cancelEditing", params: { documentId: document_id }); end
25
+
26
+ def create_embedded_request_url(body); @client.post("/v1/document/createEmbeddedRequestUrl", body: body); end
27
+ def create_embedded_edit_url(body); @client.post("/v1/document/createEmbeddedEditUrl", body: body); end
28
+ def get_embedded_sign_link(**params); @client.get("/v1/document/getEmbeddedSignLink", params); end
29
+
30
+ def download(document_id); @client.download("/v1/document/download", documentId: document_id); end
31
+ def download_attachment(**params); @client.download("/v1/document/downloadAttachment", params); end
32
+ def download_audit_log(document_id); @client.download("/v1/document/downloadAuditLog", documentId: document_id); end
33
+
34
+ def revoke(document_id, body = {}); @client.post("/v1/document/revoke", body: body, params: { documentId: document_id }); end
35
+ def remind(document_id, body = {}); @client.post("/v1/document/remind", body: body, params: { documentId: document_id }); end
36
+ def delete(document_id); @client.delete("/v1/document/delete", documentId: document_id); end
37
+ def extend_expiry(document_id, body); @client.patch("/v1/document/extendExpiry", body: body, params: { documentId: document_id }); end
38
+
39
+ def change_access_code(document_id, body); @client.patch("/v1/document/changeAccessCode", body: body, params: { documentId: document_id }); end
40
+ def change_recipient(document_id, body); @client.patch("/v1/document/changeRecipient", body: body, params: { documentId: document_id }); end
41
+
42
+ def add_tags(body); @client.patch("/v1/document/addTags", body: body); end
43
+ def delete_tags(body); @client.delete("/v1/document/deleteTags", body: body); end
44
+
45
+ def remove_authentication(document_id, body); @client.patch("/v1/document/RemoveAuthentication", body: body, params: { documentId: document_id }); end
46
+ def add_authentication(document_id, body); @client.patch("/v1/document/addAuthentication", body: body, params: { documentId: document_id }); end
47
+
48
+ def prefill_fields(document_id, body); @client.patch("/v1/document/prefillFields", body: body, params: { documentId: document_id }); end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,12 @@
1
+ module Boldsign
2
+ module Resources
3
+ # Identity-verification endpoints (`/v1/identityVerification/*`).
4
+ class IdentityVerification < Resource
5
+ def report(body); @client.post("/v1/identityVerification/report", body: body); end
6
+ def image(body); @client.post("/v1/identityVerification/image", body: body); end
7
+ def create_embedded_url(body)
8
+ @client.post("/v1/identityVerification/createEmbeddedVerificationUrl", body: body)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ module Boldsign
2
+ module Resources
3
+ # Plan / billing endpoints (`/v1/plan/*`).
4
+ class Plan < Resource
5
+ def api_credits_count; @client.get("/v1/plan/apiCreditsCount"); end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ module Boldsign
2
+ module Resources
3
+ # Sender-identity endpoints (`/v1/senderIdentities/*`).
4
+ class SenderIdentity < Resource
5
+ def list(**params); @client.get("/v1/senderIdentities/list", params); end
6
+ def properties(**params); @client.get("/v1/senderIdentities/properties", params); end
7
+ def create(body); @client.post("/v1/senderIdentities/create", body: body); end
8
+ def update(body, **params); @client.post("/v1/senderIdentities/update", body: body, params: params); end
9
+ def delete(**params); @client.delete("/v1/senderIdentities/delete", params); end
10
+ def resend_invitation(**params); @client.post("/v1/senderIdentities/resendInvitation", params: params); end
11
+ def rerequest(body, **params); @client.post("/v1/senderIdentities/rerequest", body: body, params: params); end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ module Boldsign
2
+ module Resources
3
+ # Team endpoints (`/v1/teams/*`).
4
+ class Team < Resource
5
+ def list(**params); @client.get("/v1/teams/list", params); end
6
+ def get(team_id); @client.get("/v1/teams/get", teamId: team_id); end
7
+ def create(body); @client.post("/v1/teams/create", body: body); end
8
+ def update(body, **params); @client.put("/v1/teams/update", body: body, params: params); end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,37 @@
1
+ module Boldsign
2
+ module Resources
3
+ # Template endpoints (`/v1/template/*`) — create, send, edit, and embed
4
+ # reusable signing templates.
5
+ #
6
+ # @see https://developers.boldsign.com/templates
7
+ class Template < Resource
8
+ def list(**params); @client.get("/v1/template/list", params); end
9
+ def properties(template_id); @client.get("/v1/template/properties", templateId: template_id); end
10
+ def download(template_id); @client.download("/v1/template/download", templateId: template_id); end
11
+
12
+ def create(body); @client.post("/v1/template/create", body: body); end
13
+ def edit(template_id, body); @client.put("/v1/template/edit", body: body, params: { templateId: template_id }); end
14
+ def delete(template_id); @client.delete("/v1/template/delete", templateId: template_id); end
15
+
16
+ def send_template(template_id, body)
17
+ @client.post("/v1/template/send", body: body, params: { templateId: template_id })
18
+ end
19
+ def merge_and_send(body); @client.post("/v1/template/mergeAndSend", body: body); end
20
+
21
+ def create_embedded_template_url(body); @client.post("/v1/template/createEmbeddedTemplateUrl", body: body); end
22
+ def get_embedded_template_edit_url(body); @client.post("/v1/template/getEmbeddedTemplateEditUrl", body: body); end
23
+ def create_embedded_request_url(template_id, body)
24
+ @client.post("/v1/template/createEmbeddedRequestUrl", body: body, params: { templateId: template_id })
25
+ end
26
+ def merge_create_embedded_request_url(body)
27
+ @client.post("/v1/template/mergeCreateEmbeddedRequestUrl", body: body)
28
+ end
29
+ def create_embedded_preview_url(body)
30
+ @client.post("/v1/template/createEmbeddedPreviewUrl", body: body)
31
+ end
32
+
33
+ def add_tags(body); @client.patch("/v1/template/addTags", body: body); end
34
+ def delete_tags(body); @client.delete("/v1/template/deleteTags", body: body); end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ module Boldsign
2
+ module Resources
3
+ # User-management endpoints (`/v1/users/*`).
4
+ class User < Resource
5
+ def list(**params); @client.get("/v1/users/list", params); end
6
+ def get(user_id); @client.get("/v1/users/get", userId: user_id); end
7
+ def create(body); @client.post("/v1/users/create", body: body); end
8
+ def update(body, **params); @client.put("/v1/users/update", body: body, params: params); end
9
+ def update_metadata(body, **params); @client.put("/v1/users/updateMetaData", body: body, params: params); end
10
+ def change_team(body, **params); @client.put("/v1/users/changeTeam", body: body, params: params); end
11
+ def resend_invitation(**params); @client.post("/v1/users/resendInvitation", params: params); end
12
+ def cancel_invitation(**params); @client.post("/v1/users/cancelInvitation", params: params); end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module Boldsign
2
+ VERSION = "0.1.0"
3
+ end
data/lib/boldsign.rb ADDED
@@ -0,0 +1,69 @@
1
+ require "faraday"
2
+ require "faraday/multipart"
3
+ require "json"
4
+
5
+ require_relative "boldsign/version"
6
+ require_relative "boldsign/error"
7
+ require_relative "boldsign/client"
8
+ require_relative "boldsign/resource"
9
+ require_relative "boldsign/resources/brand"
10
+ require_relative "boldsign/resources/contact"
11
+ require_relative "boldsign/resources/contact_group"
12
+ require_relative "boldsign/resources/custom_field"
13
+ require_relative "boldsign/resources/document"
14
+ require_relative "boldsign/resources/identity_verification"
15
+ require_relative "boldsign/resources/plan"
16
+ require_relative "boldsign/resources/sender_identity"
17
+ require_relative "boldsign/resources/team"
18
+ require_relative "boldsign/resources/template"
19
+ require_relative "boldsign/resources/user"
20
+
21
+ # Top-level namespace for the BoldSign Ruby client.
22
+ #
23
+ # Configure once at boot and access a shared {Client} via {Boldsign.client}, or
24
+ # instantiate {Client} directly when you need multiple credentials/regions.
25
+ #
26
+ # @example Configure and use the shared client
27
+ # Boldsign.configure do |c|
28
+ # c.api_key = ENV["BOLDSIGN_API_KEY"]
29
+ # c.region = :us
30
+ # end
31
+ # Boldsign.client.documents.list
32
+ module Boldsign
33
+ # Region → base URL map for BoldSign's regional API hosts.
34
+ REGIONS = {
35
+ us: "https://api.boldsign.com",
36
+ eu: "https://api-eu.boldsign.com",
37
+ ca: "https://api-ca.boldsign.com",
38
+ au: "https://api-au.boldsign.com"
39
+ }.freeze
40
+
41
+ class << self
42
+ # @return [String, nil] API key used by the shared {client}.
43
+ attr_accessor :api_key
44
+
45
+ # @return [Symbol, nil] Region key (`:us`, `:eu`, `:ca`, `:au`).
46
+ attr_accessor :region
47
+
48
+ # @return [String, nil] Optional explicit base URL override (takes precedence over {region}).
49
+ attr_accessor :base_url
50
+
51
+ # Yields self for block-style configuration.
52
+ # @yieldparam config [Boldsign] the module itself
53
+ # @return [void]
54
+ def configure
55
+ yield self
56
+ end
57
+
58
+ # @return [Client] memoized shared client built from module-level config.
59
+ def client
60
+ @client ||= Client.new(api_key: api_key, region: region, base_url: base_url)
61
+ end
62
+
63
+ # Clears the memoized shared client so the next call to {client} rebuilds it.
64
+ # @return [void]
65
+ def reset!
66
+ @client = nil
67
+ end
68
+ end
69
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: boldsign
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - James Klein
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: faraday
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '2.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '2.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: faraday-multipart
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '1.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rake
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '13.0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '13.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: rspec
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.12'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.12'
68
+ - !ruby/object:Gem::Dependency
69
+ name: webmock
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.19'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.19'
82
+ description: A Ruby wrapper for the BoldSign REST API (documents, templates, contacts,
83
+ teams, brands, webhooks, and more).
84
+ email:
85
+ - kleinjm007@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - CHANGELOG.md
91
+ - LICENSE.txt
92
+ - README.md
93
+ - boldsign.gemspec
94
+ - lib/boldsign.rb
95
+ - lib/boldsign/client.rb
96
+ - lib/boldsign/error.rb
97
+ - lib/boldsign/resource.rb
98
+ - lib/boldsign/resources/brand.rb
99
+ - lib/boldsign/resources/contact.rb
100
+ - lib/boldsign/resources/contact_group.rb
101
+ - lib/boldsign/resources/custom_field.rb
102
+ - lib/boldsign/resources/document.rb
103
+ - lib/boldsign/resources/identity_verification.rb
104
+ - lib/boldsign/resources/plan.rb
105
+ - lib/boldsign/resources/sender_identity.rb
106
+ - lib/boldsign/resources/team.rb
107
+ - lib/boldsign/resources/template.rb
108
+ - lib/boldsign/resources/user.rb
109
+ - lib/boldsign/version.rb
110
+ homepage: https://github.com/kleinjm/boldsign-ruby
111
+ licenses:
112
+ - MIT
113
+ metadata:
114
+ homepage_uri: https://github.com/kleinjm/boldsign-ruby
115
+ source_code_uri: https://github.com/kleinjm/boldsign-ruby
116
+ changelog_uri: https://github.com/kleinjm/boldsign-ruby/blob/main/CHANGELOG.md
117
+ bug_tracker_uri: https://github.com/kleinjm/boldsign-ruby/issues
118
+ documentation_uri: https://rubydoc.info/gems/boldsign
119
+ rubygems_mfa_required: 'true'
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '3.0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubygems_version: 3.6.9
135
+ specification_version: 4
136
+ summary: Ruby client for the BoldSign e-signature API
137
+ test_files: []