Active Call - nCino KYC DocFox
DocFox exposes the nCino KYC DocFox API endpoints through Active Call service objects.
- Installation
- Configuration
- Usage
- Using call
- Using call!
- When to use call or call!
- Using lists
- Service Objects
- Development
- Contributing
- License
Installation
Install the gem and add to the application's Gemfile by executing:
bundle add active_call-doc_foxIf bundler is not being used to manage dependencies, install the gem by executing:
gem install active_call-doc_foxConfiguration
Configure your API credentials.
In a Rails application, the standard practice is to place this code in a file named doc_fox.rb within the config/initializers directory.
require 'active_call-doc_fox'
DocFox::BaseService.configure do |config|
config.api_key = ''
config.secret = ''
# Optional configuration.
config.cache = Rails.cache # Default: ActiveSupport::Cache::MemoryStore.new
config.logger = Rails.logger # Default: Logger.new($stdout)
config.logger_level = :debug # Default: :info
config.log_headers = true # Default: false
config.log_bodies = true # Default: false
endUsage
Each service object returned will undergo validation before the call method is invoked to access API endpoints.
After successful validation.
service.success? # => true
service.errors # => #<ActiveModel::Errors []>After failed validation.
service.success? # => false
service.errors # => #<ActiveModel::Errors [#<ActiveModel::Error attribute=id, type=blank, options={}>]>
service.errors.full_messages # => ["Id can't be blank"]After a successful call invocation, the response attribute will contain a Faraday::Response object.
service.success? # => true
service.response # => #<Faraday::Response ...>
service.response.success? # => true
service.response.status # => 200
service.response.body # => {"data"=>{"id"=>"aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb", "type"=>"kyc_application", "attributes"=>{}}, ...}At this point you will also have a facade object which will hold all the attributes for the specific resource.
service.facade # => #<DocFox::KycApplication::Facade @kyc_entity_type_name="South African Citizen" ...>
service.facade.kyc_entity_type_name # => 'South African Citizen'For convenience, facade attributes can be accessed directly on the service object.
service.kyc_entity_type_name # => 'South African Citizen'After a failed call invocation, the response attribute will still contain a Faraday::Response object.
service.success? # => false
service.errors # => #<ActiveModel::Errors [#<ActiveModel::Error attribute=base, type=not_found, options={}>]>
service.errors.full_messages # => ["Not Found"]
service.response # => #<Faraday::Response ...>
service.response.success? # => false
service.response.status # => 404
service.response.body # => {"errors"=>[{"title"=>"not_found", "status"=>"404", "detail"=>"The resource you requested could not be found"}]}Each service object returned will undergo validation before the call! method is invoked to access API endpoints.
After successful validation.
service.success? # => trueAfter failed validation, a DocFox::ValidationError exception will be raised with an errors attribute which
will contain an ActiveModel::Errors object.
rescue DocFox::ValidationError => exception
exception.message # => ''
exception.errors # => #<ActiveModel::Errors [#<ActiveModel::Error attribute=id, type=blank, options={}>]>
exception.errors.full_messages # => ["Id can't be blank"]After a successful call! invocation, the response attribute will contain a Faraday::Response object.
service.success? # => true
service.response # => #<Faraday::Response ...>
service.response.success? # => true
service.response.status # => 200
service.response.body # => {"data"=>{"id"=>"aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb", "type"=>"kyc_application", "attributes"=>{}}, ...}At this point you will also have a facade object which will hold all the attributes for the specific resource.
service.facade # => #<DocFox::KycApplication::Facade @kyc_entity_type_name="South African Citizen" ...>
service.facade.kyc_entity_type_name # => 'South African Citizen'For convenience, facade attributes can be accessed directly on the service object.
service.kyc_entity_type_name # => 'South African Citizen'After a failed call! invocation, a DocFox::RequestError will be raised with a response attribute which will contain a Faraday::Response object.
rescue DocFox::RequestError => exception
exception.message # => 'Not Found'
exception.errors # => #<ActiveModel::Errors [#<ActiveModel::Error attribute=base, type=not_found, options={}>]>
exception.errors.full_messages # => ["Not Found"]
exception.response # => #<Faraday::Response ...>
exception.response.status # => 404
exception.response.body # => {"errors"=>[{"title"=>"not_found", "status"=>"404", "detail"=>"The resource you requested could not be found"}]}An example of where to use call would be in a controller doing an inline synchronous request.
class SomeController < ApplicationController
def update
@service = DocFox::KycApplication::UpdateService.call(**params)
if @service.success?
redirect_to [@service], notice: 'Success', status: :see_other
else
flash.now[:alert] = @service.errors.full_messages.to_sentence
render :edit, status: :unprocessable_entity
end
end
endAn example of where to use call! would be in a job doing an asynchronous request.
You can use the exceptions to determine which retry strategy to use and which to discard.
class SomeJob < ApplicationJob
discard_on DocFox::NotFoundError
retry_on DocFox::RequestTimeoutError, wait: 5.minutes, attempts: :unlimited
retry_on DocFox::TooManyRequestsError, wait: :polynomially_longer, attempts: 10
def perform
DocFox::KycApplication::UpdateService.call!(**params)
end
endUsing lists
If you don't provide the per_page argument, multiple API requests will be made untill all records have been returned. You could be rate limited, so use wisely.
Service Objects
KYC Applications
List KYC applications
# https://www.docfoxapp.com/api/v2/documentation#tag/KYC-Applications/paths/~1api~1v2~1kyc_applications/get
DocFox::KycApplication::ListService.call(page: 1, per_page: 10).each do |facade|
facade.id
endFilter by names, numbers contact information or external refs.
DocFox::KycApplication::ListService.call(search_term: 'eric.cartman@example.com').map { _1 }Get a KYC application
# https://www.docfoxapp.com/api/v2/documentation#tag/KYC-Applications/paths/~1api~1v2~1kyc_applications~1%7Bkyc_application_id%7D/get
service = DocFox::KycApplication::GetService.call(id: '')
service.id
service.approved_at
service.archived
service.created_at
service.status
service.relationships.dig('profile', 'data', 'id')
service.relationships.dig('data_requirements', 'links', 'related')
...Include related resources.
managed_by, profile.additional_details, profile.addresses, profile.contacts, profile.names, profile.numbers, parent_related_entities, onboarding_token_summary, onboarding_token_summary.status_summaries, onboarding_token_summary.data_requirement_summaries, onboarding_token_summary.kyc_entity_template_designation_schema, onboarding_token_summary.parent_related_entity_designation_summary, onboarding_token_summary.parent_onboarding_token_summary, onboarding_token_summary.relationship_builder_config
service = DocFox::KycApplication::GetService.call(id: '', params: { include: 'managed_by,profile.names' })
service.includedCreate a KYC application
# https://www.docfoxapp.com/api/v2/documentation#tag/KYC-Applications/paths/~1api~1v2~1kyc_applications/post
DocFox::KycApplication::CreateService.call(
data: {
type: 'kyc_application',
attributes: {
kyc_entity_template_id: 'aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb',
names: {
first_names: 'Eric Theodore',
last_names: 'Cartman'
},
# ...more fields following the schema definitions.
}
}
)Approve a KYC application
# https://www.docfoxapp.com/api/v2/documentation#tag/KYC-Applications/paths/~1api~1v2~1kyc_applications~1%7Bkyc_application_id%7D~1approve/patch
DocFox::KycApplication::ApproveService.call(id: '')Unapprove a KYC application
# https://www.docfoxapp.com/api/v2/documentation#tag/KYC-Applications/paths/~1api~1v2~1kyc_applications~1%7Bkyc_application_id%7D~1unapprove/patch
DocFox::KycApplication::UnapproveService.call(id: '', reason: '')Transfer a KYC application
# https://www.docfoxapp.com/api/v2/documentation#tag/KYC-Applications/paths/~1api~1v2~1kyc_applications~1%7Bkyc_application_id%7D~1transfer/patch
DocFox::KycApplication::TransferService.call(id: '', transfer_to_user_id: '')Archive a KYC application
# https://www.docfoxapp.com/api/v2/documentation#tag/KYC-Applications/paths/~1api~1v2~1kyc_applications~1%7Bkyc_application_id%7D~1archive/post
DocFox::KycApplication::ArchiveService.call(id: '', reason: '')Unarchive a KYC application
# https://www.docfoxapp.com/api/v2/documentation#tag/KYC-Applications/paths/~1api~1v2~1kyc_applications~1%7Bkyc_application_id%7D~1unarchive/post
DocFox::KycApplication::UnarchiveService.call(id: '', reason: '')Delete a KYC application
# https://www.docfoxapp.com/api/v2/documentation#tag/KYC-Applications/paths/~1api~1v2~1kyc_applications~1%7Bkyc_application_id%7D/delete
DocFox::KycApplication::DeleteService.call(id: '')Status Summaries
Get a status summary of a KYC application
# https://www.docfoxapp.com/api/v2/documentation#tag/Status-Summaries/paths/~1api~1v2~1kyc_applications~1%7Bkyc_application_id%7D~1status_summaries/get
service = DocFox::StatusSummary::GetService.call(id: '')
service.id
service.overall_kyc_application_status
service.module_statuses
...Profiles
List profiles
# https://www.docfoxapp.com/api/v2/documentation#tag/Profiles/paths/~1api~1v2~1kyc_applications~1%7Bkyc_application_id%7D~1profiles/get
DocFox::Profile::ListService.call(kyc_application_id: '', page: 1, per_page: 10).each do |facade|
facade.id
endGet a profile
# https://www.docfoxapp.com/api/v2/documentation#tag/Profiles/paths/~1api~1v2~1profiles~1%7Bprofile_id%7D/get
service = DocFox::Profile::GetService.call(id: '')
service.id
service.created_at
...Include related resources.
additional_details, addresses, contacts, contacts.invitation_tokens, names, numbers
service = DocFox::Profile::GetService.call(id: '', params: { include: 'names,numbers,additional_details' })
service.includedData Requirements
List data requirements
# https://www.docfoxapp.com/api/v2/documentation#tag/Data-Requirements/paths/~1api~1v2~1kyc_applications~1%7Bkyc_application_id%7D~1data_requirements/get
DocFox::DataRequirement::ListService.call(kyc_application_id: '', page: 1, per_page: 10).each do |facade|
facade.id
endList only data requirements for forms.
DocFox::DataRequirement::ListService.call(kyc_application_id: '', forms: true).map { _1 }List data requirements associated with an account application
# https://www.docfoxapp.com/api/v2/documentation#tag/Data-Requirements/paths/~1api~1v2~1account_applications~1%7Baccount_application_id%7D~1data_requirements/get
DocFox::DataRequirement::ListService.call(account_application_id: '', page: 1, per_page: 10).each do |facade|
facade.id
endList only data requirements for forms.
DocFox::DataRequirement::ListService.call(account_application_id: '', forms: true).map { _1 }Get a data requirement
# https://www.docfoxapp.com/api/v2/documentation#tag/Data-Requirements/paths/~1api~1v2~1data_requirements~1%7Bdata_requirement_id%7D/get
service = DocFox::DataRequirement::GetService.call(id: '')
service.id
service.created_at
service.form
service.name
service.required
service.slug
service.valid_evidence_types
...Include related resources.
evidence_submissions, active_evidence_submission, active_evidence_submission.form, active_evidence_submission.form.active_form_datum
service = DocFox::DataRequirement::GetService.call(id: '', params: { include: 'evidence_submissions,active_evidence_submission' })
service.includedKYC Entity Templates
List KYC entity templates
# https://www.docfoxapp.com/api/v2/documentation#tag/KYC-Entity-Templates/paths/~1api~1v2~1kyc_entity_templates/get
DocFox::KycEntityTemplate::ListService.call(page: 1, per_page: 10).each do |facade|
facade.id
endGet a KYC entity template
# https://www.docfoxapp.com/api/v2/documentation#tag/KYC-Entity-Templates/paths/~1api~1v2~1kyc_entity_templates~1%7Bkyc_entity_template_id%7D/get
service = DocFox::KycEntityTemplate::GetService.call(id: '')
service.id
service.kyc_entity_type_name
service.kyc_entity_type_category
service.created_at
service.profile_schema
...Evidence Submissions
List evidence submissions
# https://www.docfoxapp.com/api/v2/documentation#tag/Evidence-Submissions/paths/~1api~1v2~1data_requirements~1%7Bdata_requirement_id%7D~1evidence_submissions/get
DocFox::EvidenceSubmission::ListService.call(data_requirement_id: '', page: 1, per_page: 10).each do |facade|
facade.id
endGet an evidence submission
# https://www.docfoxapp.com/api/v2/documentation#tag/Evidence-Submissions/paths/~1api~1v2~1evidence_submissions~1%7Bevidence_submission_id%7D/get
service = DocFox::EvidenceSubmission::GetService.call(id: '')
service.id
service.evidence_type
service.form
service.status
service.created_at
service.attributes
...Include related resources.
document: the related document, for document evidence submission
qualitative_checks: the related qualitative checks, for document evidence submission
rejection_reasons: the related rejection reasons
form: the related form, for form evidence submission
form.active_form_datum: the related form and its latest data submission, for form evidence submission
service = DocFox::EvidenceSubmission::GetService.call(id: '', params: { include: 'document,qualitative_checks' })
service.includedUpdate an evidence submission
At the moment this is used only to add third party data to an external evidence submission for a specific third party provider.
# https://www.docfoxapp.com/api/v2/documentation#tag/Evidence-Submissions/paths/~1api~1v2~1evidence_submissions~1%7Bevidence_submission_id%7D/patch
DocFox::EvidenceSubmission::UpdateService.call(
id: '',
data: {
type: 'evidence_submission',
id: '',
attributes: {
results: {
dob: '1984-01-01',
gender: 'M',
surname: 'Cartman',
forename1: 'Eric',
forename2: nil,
id_number: '8401017223183',
addresses: {
address: [
{
addr_type: 'R',
addr_line1: '28201 E. Bonanza St.',
addr_line2: '',
addr_line3: '',
addr_line4: 'South Park',
addr_postal_code: '8000',
addr_update_date: '2017-11-21'
}
]
},
telephones: {
telephone: [
{
tel_num: '27715555555',
tel_type: 'Cell',
tel_update_date: '2017-09-05'
}
]
},
deceased_date: nil,
deceased_flag: 'N',
verified_date: '2015-06-23',
verified_flag: 'Y',
deceased_reason: nil
}
}
}
)Reject an active evidence submission
# https://www.docfoxapp.com/api/v2/documentation#tag/Evidence-Submissions/paths/~1api~1v2~1evidence_submissions~1%7Bevidence_submission_id%7D~1reject/patch
DocFox::EvidenceSubmission::RejectService.call(id: '', reason: '')Approve an active evidence submission
# https://www.docfoxapp.com/api/v2/documentation#tag/Evidence-Submissions/paths/~1api~1v2~1evidence_submissions~1%7Bevidence_submission_id%7D~1approve/patch
DocFox::EvidenceSubmission::ApproveService.call(id: '')Replace an active evidence submission
# https://www.docfoxapp.com/api/v2/documentation#tag/Evidence-Submissions/paths/~1api~1v2~1evidence_submissions~1%7Bevidence_submission_id%7D~1replace/patch
DocFox::EvidenceSubmission::ReplaceService.call(id: '')Documents
List documents
# https://www.docfoxapp.com/api/v2/documentation#tag/Documents/paths/~1api~1v2~1evidence_submissions~1%7Bevidence_submission_id%7D~1documents/get
DocFox::Document::ListService.call(evidence_submission_id: '', page: 1, per_page: 10).each do |facade|
facade.id
endGet a document
# https://www.docfoxapp.com/api/v2/documentation#tag/Documents/paths/~1api~1v2~1documents~1%7Bdocument_id%7D/get
service = DocFox::Document::GetService.call(id: '')
service.id
service.created_at
service.content_type
service.filename
service.token
service.token_expiry
service.uploaded_by
...Include related resources.
evidence_submissions
service = DocFox::Document::GetService.call(id: '', params: { include: 'evidence_submissions' })
service.includedDocument Tokens
List document tokens
# https://www.docfoxapp.com/api/v2/documentation#tag/Document-Tokens/paths/~1api~1v2~1documents~1%7Bdocument_id%7D~1document_tokens/get
DocFox::DocumentToken::ListService.call(document_id: '', page: 1, per_page: 10).each do |facade|
facade.id
endGet a document token
# https://www.docfoxapp.com/api/v2/documentation#tag/Document-Tokens/paths/~1api~1v2~1document_tokens~1%7Bdocument_token_id%7D/get
service = DocFox::DocumentToken::GetService.call(id: '')
service.id
service.created_at
service.expiry
service.content_type
...Create a document token
# https://www.docfoxapp.com/api/v2/documentation#tag/Document-Tokens/paths/~1api~1v2~1documents~1%7Bdocument_id%7D~1document_tokens/post
DocFox::DocumentToken::CreateService.call(
document_id: '',
data: {
type: 'document_token'
}
)Download Documents
Download a document file
# https://www.docfoxapp.com/api/v2/documentation#tag/Download-Documents/paths/~1api~1v2~1document_file_downloads~1%7Bdocument_token_id%7D/get
service = DocFox::Document::DownloadService.call(document_token_id: '', content_type: 'image/jpeg')
service.response.body # => "\xFF\xD8\xFF\xDB\x00\x84\x00\x04\x05\x..."Possible values for content_type.
image/jpegimage/pngapplication/pdf
You can also provide just the document_id and the service will automatically request the document_token_id and content_type for you.
service = DocFox::Document::DownloadService.call(document_id: '')
service.response.body # => "\xFF\xD8\xFF\xDB\x00\x84\x00\x04\x05\x..."Document Uploads
Upload a document file
# https://www.docfoxapp.com/api/v2/documentation#tag/Document-Uploads/paths/~1api~1v2~1evidence_submissions~1%7Bevidence_submission_id%7D~1documents/post
DocFox::Document::UploadService.call(
evidence_submission_id: '',
data: {
type: 'document',
attributes: {
evidence_type: 'taxes_paid_in_prior_quarter',
filename: 'taxes_paid.png',
document_data: "data:image/png;base64,#{Base64.encode64(File.read('/path/to/taxes_paid.png'))}"
}
}
)Users
List users
# https://www.docfoxapp.com/api/v2/documentation#tag/Users/paths/~1api~1v2~1users/get
DocFox::User::ListService.call(page: 1, per_page: 10).each do |facade|
facade.id
endGet a user
# https://www.docfoxapp.com/api/v2/documentation#tag/Users/paths/~1api~1v2~1users~1%7Buser_id%7D/get
service = DocFox::User::GetService.call(id: '')
service.id
service.email
service.first_names
service.last_names
service.deactivated
...Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/kobusjoubert/doc_fox.
License
The gem is available as open source under the terms of the MIT License.