Class: EasyDocForms::Client

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

Overview

Client for the EasyDocForms Partner API. Thread-safe; standard library only.

client = EasyDocForms::Client.new("edfk_live_...")
client.ping # => { org_id: "...", key_name: "...", scopes: [...] }

All methods return Hashes with symbol keys, shaped exactly like the API's JSON (see https://easydocforms.com/docs/api). API failures raise EasyDocForms::APIError subclasses.

Constant Summary collapse

USER_AGENT =
"easydocforms-ruby/#{VERSION}"

Instance Method Summary collapse

Constructor Details

#initialize(api_key, base_url: DEFAULT_BASE_URL, open_timeout: 10, read_timeout: 60) ⇒ Client

Returns a new instance of Client.

Parameters:

  • api_key (String)

    an edfk_live_* key, created in the EasyDocForms app under Settings → Integrations → Partner API (shown exactly once).

Raises:

  • (ArgumentError)


22
23
24
25
26
27
28
29
# File 'lib/easydocforms/client.rb', line 22

def initialize(api_key, base_url: DEFAULT_BASE_URL, open_timeout: 10, read_timeout: 60)
  raise ArgumentError, "api_key is required" if api_key.to_s.empty?

  @api_key = api_key
  @base_url = base_url.sub(%r{/+\z}, "")
  @open_timeout = open_timeout
  @read_timeout = read_timeout
end

Instance Method Details

Mints a hosted URL where a patient fills the form (scope fill_links:write). external_ref is an opaque correlation id echoed on submissions and webhooks — it must never contain PHI.



81
82
83
84
85
86
87
88
# File 'lib/easydocforms/client.rb', line 81

def create_fill_link(template_id:, expires_in_days: nil, max_responses: nil, external_ref: nil)
  request(:post, "/fill-links", body: {
    template_id: template_id,
    expires_in_days: expires_in_days,
    max_responses: max_responses,
    external_ref: external_ref
  })
end

#create_import(filename:, blank_form_attestation:, pdf_url: nil, pdf_base64: nil, title: nil) ⇒ Object

Imports a blank PDF (async; scope imports:write). Supply exactly one of pdf_url (public HTTPS) or pdf_base64. blank_form_attestation must be true: you attest the PDF is a blank template with no patient information (PHI). Returns { import_id:, status: "queued" } immediately; processing typically takes 1–10 minutes.



42
43
44
45
46
47
48
49
50
# File 'lib/easydocforms/client.rb', line 42

def create_import(filename:, blank_form_attestation:, pdf_url: nil, pdf_base64: nil, title: nil)
  request(:post, "/imports", body: {
    pdf_url: pdf_url,
    pdf_base64: pdf_base64,
    filename: filename,
    title: title,
    blank_form_attestation: blank_form_attestation
  })
end

#create_webhook(url:, events: nil) ⇒ Object

Registers a webhook delivery URL (scope webhooks:manage). The returned :secret (whsec_*) is shown exactly once — store it; it verifies the X-EDF-Signature header (see EasyDocForms::Webhook). events filters deliveries; nil or empty = all events.



116
117
118
# File 'lib/easydocforms/client.rb', line 116

def create_webhook(url:, events: nil)
  request(:post, "/webhooks", body: { url: url, events: events })
end

#delete_webhook(webhook_id) ⇒ Object

Deactivates a subscription (scope webhooks:manage).



127
128
129
# File 'lib/easydocforms/client.rb', line 127

def delete_webhook(webhook_id)
  request(:delete, "/webhooks/#{encode(webhook_id)}")
end

#download_submission_pdf(submission_id) ⇒ Object

The completed, pixel-exact PDF as a binary string (scope submissions:read). Works even while completed_pdf_status is "pending" (renders on demand — just slower).



99
100
101
# File 'lib/easydocforms/client.rb', line 99

def download_submission_pdf(submission_id)
  request(:get, "/submissions/#{encode(submission_id)}/pdf", raw: true)
end

#get_import(import_id) ⇒ Object

Polls an import job (scope imports:write). Result fields appear when :status is "succeeded"; :error when "failed".



54
55
56
# File 'lib/easydocforms/client.rb', line 54

def get_import(import_id)
  request(:get, "/imports/#{encode(import_id)}")
end

#get_submission(submission_id) ⇒ Object

A patient submission: structured :answers plus correlation back to the fill link that produced it (scope submissions:read).



92
93
94
# File 'lib/easydocforms/client.rb', line 92

def get_submission(submission_id)
  request(:get, "/submissions/#{encode(submission_id)}")
end

A time-limited signed URL (~10 minutes) that downloads the completed PDF without any Authorization header (scope submissions:read) — safe to hand onward without embedding your API key. Raises EasyDocForms::PDFPendingError while the frozen artifact isn't ready; fall back to #download_submission_pdf.



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

def get_submission_pdf_link(submission_id)
  request(:get, "/submissions/#{encode(submission_id)}/pdf-link")
end

#list_templatesObject

The organization's active templates, newest first (scope templates:read). Returns the array of template hashes.



74
75
76
# File 'lib/easydocforms/client.rb', line 74

def list_templates
  request(:get, "/templates").fetch(:templates)
end

#list_webhooksObject

Active subscriptions, newest first, without secrets (scope webhooks:manage). Returns the array of webhook hashes.



122
123
124
# File 'lib/easydocforms/client.rb', line 122

def list_webhooks
  request(:get, "/webhooks").fetch(:webhooks)
end

#pingObject

Proves the key authenticates, names its organization, and echoes its scopes. Requires no scope.



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

def ping
  request(:get, "/ping")
end

#test_webhook(webhook_id) ⇒ Object

Synchronously delivers one signed test event so you can verify your receiver end to end (scope webhooks:manage). Returns { delivered:, status_code: } — delivery failure is reported there, not raised.



135
136
137
# File 'lib/easydocforms/client.rb', line 135

def test_webhook(webhook_id)
  request(:post, "/webhooks/#{encode(webhook_id)}/test")
end

#wait_for_import(import_id, poll_interval: 5, timeout: 900) ⇒ Object

Polls #get_import until the job reaches a terminal status ("succeeded" or "failed") and returns it — a failed import is returned, not raised. Raises EasyDocForms::Error after timeout seconds.



61
62
63
64
65
66
67
68
69
70
# File 'lib/easydocforms/client.rb', line 61

def wait_for_import(import_id, poll_interval: 5, timeout: 900)
  deadline = Time.now + timeout
  loop do
    import = get_import(import_id)
    return import if %w[succeeded failed].include?(import[:status])
    raise Error, "timed out after #{timeout}s waiting for import #{import_id}" if Time.now >= deadline

    sleep(poll_interval)
  end
end