notarize-node-client
v0.1.6
Published
Node.js Client for Notarize.com Business API
Downloads
1,046
Readme
notarize-node-client
notarize-node-client
is a Node/JS and TypeScript Client for
Notarize.com that allows you to use normal Node
syntax to start notarizations - as opposed to writing a client based on the
REST endpoints documented on the Notarize.com Developer portal.
Install
# with npm
$ npm install notarize-node-client
Usage
This README isn't going to cover all the specifics of what Notarize.com is, and how to use it - it's targeted as a companion to the Notarize developer docs that explain each of the endpoints and how the general Notarize workflow works.
However, we'll put in plenty of examples so that it's clear how to use this library to interact with Notarize.com.
Getting your API Key
As documented on the Notarize.com site, the first step is getting an API Key
for the calls to Notarize.com. This is available on their API Keys
page, once you login. For the
rest of this document, the API Key will be seen as: [Your API Key]
, and will
need to be replaced with the API Key you obtain from the site.
Creating the Client
All Notarize functions are available from the client, and the basic construction of the client is:
import { Notarize } from 'notarize-node-client'
const client = new Notarize('[Your API Key]')
If you'd like to provide the webhook URL in the constructor, you can do that with:
const client = new Notarize(
'[Your API Key]',
{
webhookUrl: 'https://my.service.com/notarize/callback'
}
)
where the options can include:
webhookUrl
- the URL for all Notarize updates to be sentwebhookHeader
- the header to be sent on each of the calls for authentication, or validation by the receiver.
Document Calls
Get a Document
const doc = await client.document.get(id, transactionId)
This will get the document with id
, in the transaction with transactionId
and return that data. The response will be something like:
{
"success": true,
"document": {
"id": "do_9f7b097a-6469-41dc-86b9-c7aa9743cfc4",
"dateCreated": "2021-03-26T19:57:37.946749Z",
"dateUpdated": "2021-03-26T19:57:39.216662Z",
"documentName": "dummy.pdf",
"allowedActions": [
"CUSTOMER_CAN_ANNOTATE",
"ESIGN_REQUIRED"
],
"bundlePosition": 2,
"isEnote": false,
"trackingId": null,
"signedUrl": null,
"processingState": "done",
"processingError": null,
"permissions": [
"CUSTOMER_CAN_ANNOTATE",
"ESIGN_REQUIRED"
],
"signingDesignations": [],
"signingType": "NOTARIZATION",
"data": "...BASE64STRING..."
}
}
If there had been an error, the response would be:
{
"success": false,
"errors": [ "(Error message from Notarize.com...)" ]
}
So looking at the success
value of the response will quickly let you know the outcome of the call.
Update a Document
const doc = await client.document.update(id, opts)
where opts
is an Object with one or more of these optional properties:
{
name?: string;
trackingId?: string;
customerCanAnnotate?: boolean;
notarizationRequired?: boolean;
identityConfirmationRequired?: boolean;
witnessRequired?: boolean;
authorizationHeader?: string;
}
This will update the document with id
, assuming the transaction it's in is
still draft
. The response will be something like:
{
"success": true,
"document": {
"id": "do_29f983a4-8485-4afb-8343-95996f75c2d5",
"date_created": "2017-05-10T13:10:20.702098Z",
"date_updated": "2017-05-10T13:10:20.702098Z",
"document_name": "document.pdf",
"allowed_actions": ["CUSTOMER_CAN_ANNOTATE"],
"bundle_position": 1,
"processing_state": "pending"
}
}
Delete a Document
const doc = await client.document.delete(id)
This will delete the document with id
from the transaction it's in, assuming
the transaction is still draft
. The response will be something like:
{
"success": true,
"message": "Deleted Document abcdefghijk successfully"
}
Template Calls
List Templates
const trans = await client.template.list()
This will get the document with id
, in the transaction with transactionId
and return that data. The response will be something like:
{
"success": true,
"totalCount": 2,
"templates": [
{
"id": "od6nzpx5n",
"name": "Test Template",
"permalink": "my_first_template",
"createdAt": "2017-05-09T16:46:39.767123Z",
"updatedAt": "2017-05-09T16:46:39.767123Z"
},
{
"id": "od8zzpx7z",
"name": "Another Template",
"permalink": "my_favorite_template",
"createdAt": "2017-05-09T16:46:39.767123Z",
"updatedAt": "2017-05-09T16:46:39.767123Z"
}
]
}
Transaction Calls
Retrieve Transaction
const trans = await client.transaction.retrieve(id)
This will get the transaction with id
and the response will be something like:
{
"success": true,
"transaction": {
"id": "ot_anpr8qn",
"dateCreated": "2016-10-01T18:52:44.725Z",
"dateUpdated": "2016-10-02T20:13:54.245Z",
"signerInfo": {
"email": "[email protected]",
"firstName": "Miguel",
"lastName": "Lee",
"transactionAccessLink": "https://app.notarize.com/activate-transaction?bundle_id=some-bundle-id&code=some-code&[email protected]"
},
"documents": [{
"id": "do_c7e0e599-5e94-4ac1-a4a3-7e09f9994934",
"dateCreated": "2017-05-09T17:09:52.248711Z",
"dateUpdated": "2017-05-09T17:09:52.248711Z",
"documentName": "document.pdf",
"allowedActions": ["NOTARIZATION_REQUIRED"],
"bundlePosition": 0,
"processingState": "done",
"finalDocumentUrl": "https://s3-us-west-2.amazonaws.com/assets.notarize.com/document.pdf?AWSAccessKeyId=AKIAJVT3IPSNH662QU6A&Expires=1449430428&Signature=j%2FTzUuHJkrlbAJZGNpCm3xfxgmE%3D"
}],
"transactionName": "Miguel's TPS notarization for Leeroy.",
"transactionType": "Power of Attorney",
"detailedStatus": "started",
"messageToSigner": "Please notarize your TPS Report.",
"messageSignature": "Love, Leeroy.",
"status": "created",
"requireSecondaryPhotoId": false,
"detailedStatus": "complete",
"auditTrailUrl": "https://463675841562-notarize-productionmirror-documents.s3.amazonaws.com/a6d9272144840dd05b49_AuditTrail.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAITYYWRHD2HZKXQ%2F20210211%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210211T161632Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=cdd0b69d3017e8296936d0207c8aa376a"
}
}
Create Transaction
const trans = await client.transaction.create({
draft: true,
transactionName: 'Power of Attorney - Signer Smith',
transactionType: 'Power of Attorney',
documents: [
{
resource: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
requirement: 'notarization',
customerCanAnnotate: false
},
{
resource: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
requirement: 'notarization',
customerCanAnnotate: true
}
],
signers: [
{ email: '[email protected]' },
],
})
This will create the transaction, starting in the draft
mode so that documents
can be added, and then the transaction can be activated. The response will be
something like:
{
"success": true,
"transaction": {
"id": "ot_anpr8qn",
"status": "draft",
"dateCreated": "2019-10-01T18:52:44.725Z",
"dateUpdated": "2019-10-02T20:13:54.245Z",
"documents": [{
"id": "do_c7e0e599-5e94-4ac1-a4a3-7e09f9994934",
"dateCreated": "2019-10-02T17:09:52.248711Z",
"dateUpdated": "2019-10-02T17:09:52.248711Z",
"documentName": "document.pdf",
"allowedActions": ["NOTARIZATION_REQUIRED"],
"bundlePosition": 0,
"processingState": "pending"
}],
"signers": [{
"email": "[email protected]",
"firstName": "Signer",
"lastName": "Smith",
"transactionAccessLink": "https://app.notarize.com/activate-transaction?1234"
}],
"transactionName": "Power of Attorney - Signer Smith",
"transactionType": "Power of Attorney",
"detailedStatus": "started",
"messageToSigner": "Please notarize this power of attorney form.",
"messageSignature": "The Team"
}
}
List Transactions
const lst = await client.transaction.list()
This will list up to 10 transactions with the response:
{
"success": true,
"count": 2,
"transactions": [
{
"id": "ot_anpr8qn",
"dateCreated": "2016-10-01T18:52:44.725Z",
"dateUpdated": "2016-10-02T20:13:54.245Z",
"signerInfo": {
"email": "[email protected]",
"firstName": "Miguel",
"lastName": "Lee",
"transactionAccessLink": "https://app.notarize.com/activate-transaction?bundle_id=some-bundle-id&code=some-code&[email protected]"
},
"documents": [{
"id": "do_c7e0e599-5e94-4ac1-a4a3-7e09f9994934",
"dateCreated": "2017-05-09T17:09:52.248711Z",
"dateUpdated": "2017-05-09T17:09:52.248711Z",
"documentName": "document.pdf",
"allowedActions": ["NOTARIZATION_REQUIRED"],
"bundlePosition": 0
}],
"transactionName": "Miguel's TPS notarization for Leeroy.",
"transactionType": "Power of Attorney",
"messageToSigner": "Please notarize your TPS Report.",
"status": "sent",
"requireSecondaryPhotoId": false
},
{
"id": "ot_anpr8qn",
"dateCreated": "2016-10-01T18:52:44.725Z",
"dateUpdated": "2016-10-02T20:13:54.245Z",
"signerInfo": {
"email": "[email protected]",
"firstName": "Miguel",
"lastName": "Lee",
"transactionAccessLink": "https://app.notarize.com/activate-transaction?bundle_id=some-bundle-id&code=some-code&[email protected]"
},
"documents": [{
"id": "do_c7e0e599-5e94-4ac1-a4a3-7e09f9994934",
"dateCreated": "2017-05-09T17:09:52.248711Z",
"dateUpdated": "2017-05-09T17:09:52.248711Z",
"documentName": "pdf.pdf",
"allowedActions": ["NOTARIZATION_REQUIRED"],
"bundlePosition": 0
}, {
"id": "do_d46a3751-399f-4149-b7b2-d46aea498011",
"dateCreated": "2017-05-09T17:09:52.872688Z",
"dateUpdated": "2017-05-09T17:09:52.872688Z",
"documentName": "pdf-sample.pdf",
"allowedActions": ["NOTARIZATION_REQUIRED"],
"bundlePosition": 1
}],
"transactionName": "Miguel's TPS notarization for Leeroy.",
"transactionType": "Power of Attorney",
"detailedStatus": "started",
"messageToSigner": "Please notarize your TPS Report.",
"messageSignature": "Love, Leeroy.",
"status": "sent",
"requireSecondaryPhotoId": false
}
],
}
Yet this function also takes options:
const lst = await client.transaction.list(opts)
where the options can be:
{
limit?: number;
offset?: number;
}
So, to get the first 100, simply call:
const lst = await client.transaction.list({ limit: 100 })
Add Document
const doc = await client.transaction.addDocument(id, {
resource: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
requirement: 'esign',
customer_CanAnnotate: true
})
where id
is the id of a transaction to add the document to, and this will
return something like:
{
"success": true,
"document": {
"id": "do_29f983a4-8485-4afb-8343-95996f75c2d5",
"dateCreated": "2019-05-10T13:10:20.702098Z",
"dateUpdated": "2019-05-10T13:10:20.702098Z",
"documentName": "document.pdf",
"allowedActions": ["ESIGN_REQUIRED","CUSTOMER_CAN_ANNOTATE"],
"bundlePosition": 1,
"processingState": "pending"
}
}
Update Draft Transaction
const trans = await client.transaction.update(id, {
allowSignerAnnotations: false,
requireSecondaryPhotoId: false,
suppressEmail: false
})
where id
is the id of a transaction to update, and this will return
something like:
{
"success": true,
"transaction": {
"id": "ot_anpr8qn",
"dateCreated": "2016-10-01T18:52:44.725Z",
"dateUpdated": "2016-10-02T20:13:54.245Z",
"signerInfo": {
"email": "[email protected]",
"firstName": "Miguel",
"lastName": "Lee",
"transactionAccessLink": "https://app.notarize.com/activate-transaction?bundle_id=some-bundle-id&code=some-code&[email protected]"
},
"documents": [{
"id": "do_c7e0e599-5e94-4ac1-a4a3-7e09f9994934",
"dateCreated": "2017-05-09T17:09:52.248711Z",
"dateUpdated": "2017-05-09T17:09:52.248711Z",
"documentName": "document.pdf",
"allowedActions": ["NOTARIZATION_REQUIRED"],
"bundlePosition": 0
}],
"transactionName": "Miguel's TPS notarization for Leeroy",
"transactionType": "Power of Attorney",
"messageToSigner": "Please notarize your TPS Report.",
"messageSignature": "Love, Leeroy.",
"status": "sent",
"detailedStatus": "started",
"requireSecondary_photo_id": false
}
}
Activate Draft Transaction
const trans = await client.transaction.activate(id)
where id
is the id of a transaction to activate, and this will return
something like:
{
"success": true,
"transaction": {
"id": "ot_anpr8qn",
"dateCreated": "2016-10-01T18:52:44.725Z",
"dateUpdated": "2016-10-02T20:13:54.245Z",
"signerInfo": {
"email": "[email protected]",
"firstName": "Miguel",
"lastName": "Lee",
"transactionAccessLink": "https://app.notarize.com/activate-transaction?bundle_id=some-bundle-id&code=some-code&[email protected]"
},
"documents": [{
"id": "do_c7e0e599-5e94-4ac1-a4a3-7e09f9994934",
"dateCreated": "2017-05-09T17:09:52.248711Z",
"dateUpdated": "2017-05-09T17:09:52.248711Z",
"documentName": "pdf.pdf",
"allowedActions": ["NOTARIZATION_REQUIRED"],
"bundlePosition": 0
}, {
"id": "do_d46a3751-399f-4149-b7b2-d46aea498011",
"dateCreated": "2017-05-09T17:09:52.872688Z",
"dateUpdated": "2017-05-09T17:09:52.872688Z",
"documentName": "pdf-sample.pdf",
"allowedActions": ["NOTARIZATION_REQUIRED"],
"bundlePosition": 1
}],
"transactionName": "Miguel's TPS notarization for Leeroy.",
"transactionType": "Power of Attorney",
"detailedStatus": "sent_to_signer",
"messageToSigner": "Please notarize your TPS Report.",
"messageSignature": "Love, Leeroy.",
"status": "sent",
"requireSecondaryPhotoId": false
}
}
If you'd like to update the suppressEmail
flag on the transaction, that's
done with the optional argument on the call:
const trans = await client.transaction.activate(id, false)
will indicating that suppressEmail
should be set to false
.
Delete Transaction
const resp = await client.transaction.delete(id)
where id
is the id of a transaction to delete, and this will return
something like:
{
"success": true,
"message": "Deleted Transaction abcdefghijk successfully"
}
Resend Transaction Email
const trans = await client.transaction.resendEmail(id)
where id
is the id of a transaction to resend the email(s) for, and this
will return something like:
{
"success": true,
"transaction": {
"id": "ot_anpr8qn",
"dateCreated": "2016-10-01T18:52:44.725Z",
"dateUpdated": "2016-10-02T20:13:54.245Z",
"signerInfo": {
"email": "[email protected]",
"firstName": "Miguel",
"lastName": "Lee",
"transactionAccessLink": "https://app.notarize.com/activate-transaction?bundle_id=some-bundle-id&code=some-code&[email protected]"
},
"documents": [{
"id": "do_c7e0e599-5e94-4ac1-a4a3-7e09f9994934",
"dateCreated": "2017-05-09T17:09:52.248711Z",
"dateUpdated": "2017-05-09T17:09:52.248711Z",
"documentName": "document.pdf",
"allowedActions": ["NOTARIZATION_REQUIRED"],
"bundlePosition": 0
}],
"transactionName": "Miguel's TPS notarization for Leeroy.",
"transactionType": "Power of Attorney",
"detailedStatus": "started",
"messageToSigner": "Please notarize your TPS Report.",
"messageSignature": "Love, Leeroy.",
"status": "sent",
"requireSecondaryPhotoId": false
}
}
This function also allows the messageToSender
to be passed-into the call as
an optional parameter:
const trans = await client.transaction.resendEmail(id, 'Second email message')
Resend Transaction SMS
const trans = await client.transaction.resendSms(id)
where id
is the id of a transaction to resend the SMS message(s) for, and
this will return something like:
{
"success": true,
"transaction": {
"id": "ot_anpr8qn",
"dateCreated": "2016-10-01T18:52:44.725Z",
"dateUpdated": "2016-10-02T20:13:54.245Z",
"signerInfo": {
"email": "[email protected]",
"firstName": "Testy",
"lastName": "McTesterson",
"transactionAccessLink": "https://app.notarize.com/activate-transaction?bundle_id=some-bundle-id&code=some-code&[email protected]",
"phone": {
"countryCode": "1",
"number": "5555555555"
}
},
"documents": [{
"id": "do_c7e0e599-5e94-4ac1-a4a3-7e09f9994934",
"dateCreated": "2017-05-09T17:09:52.248711Z",
"dateUpdated": "2017-05-09T17:09:52.248711Z",
"documentName": "document.pdf",
"allowedActions": ["NOTARIZATION_REQUIRED"],
"bundlePosition": 0
}],
"transactionName": "Miguel's TPS notarization for Leeroy.",
"transactionType": "Power of Attorney",
"detailedStatus": "started",
"messageToSigner": "Please notarize your TPS Report.",
"messageSignature": "Love, Leeroy.",
"status": "sent",
"requireSecondaryPhotoId": false
}
}
This function also allows the phone
to be passed-into the call as
an optional parameter:
const trans = await client.transaction.resendSms(id, {
countryCode: '1',
number: '515-555-5555'
})
Retrieve Meeting Record
const rec = await client.transaction.retrieveMeetingRecord(id)
where id
is the id of a transaction to pull the meeting record for, and
this will return something like:
{
"success": true,
"record": {
"id": "me_rnykzyn",
"meetingStart": "2016-10-01T18:52:44.725Z",
"meetingEnd": "2016-10-01T18:58:54.245Z",
"notaryName": "Leeroy Jenkins",
"notaryRegistration": "1337",
"signerInfo": {
"email": "[email protected]",
"firstName": "Miguel",
"lastName": "Lee"
},
"notarizedDocuments": [{
"notarialActs": [
"jurat",
"verification_of_fact"
],
"documentUrl": "https://s3-us-west-2.amazonaws.com/assets.notarize.com/document.pdf?AWSAccessKeyId=AKIAJVT3IPSNH662QU6A&Expires=1449430428&Signature=j%2FTzUuHJkrlbAJZGNpCm3xfxgmE%3D"
}],
"verificationCredentials": {
"retrievalId": "CTJHT32H",
"retrievalPin": "7RNTNN",
"lastName": "Lee",
"dateCompleted": "10/19/2016"
},
"signerPhotoIdentification": {
"primaryFront": "https://s3-us-west-2.amazonaws.com/assets.notarize.com/primary_front.png?AWSAccessKeyId=AKIAJVT3IPSNH662QU6A&Expires=1449430428&Signature=j%2FTzUuHJkrlbAJZGNpCm3xfxgmE%3D",
"primaryBack": "https://s3-us-west-2.amazonaws.com/assets.notarize.com/primary_back.png?AWSAccessKeyId=AKIAJVT3IPSNH662QU6A&Expires=1449430428&Signature=j%2FTzUuHJkrlbAJZGNpCm3xfxgmE%3D",
"secondaryFront": "https://s3-us-west-2.amazonaws.com/assets.notarize.com/primary_back.png?AWSAccessKeyId=AKIAJVT3IPSNH662QU6A&Expires=1449430428&Signature=j%2FTzUuHJkrlbAJZGNpCm3xfxgmE%3D"
}
}
}
Webhook Calls
Set/Update Webhook URL
const hook = await client.webhook.update('https://my.service.com/esign/callback')
This will set, or update, the webhook URL for all subsequent calls by Notarize.com - until the webhook is deleted, or changed to something else. The response will be something like:
{
"success": true,
"webhookUrl": "https://my.service.com/esign/callback",
"header": ""
}
It's also possible to set the header
to be returned on each webhook call, by
including it as the second, optional, parameter to the call:
const hook = await client.webhook.update(
'https://my.service.com/esign/callback',
'MyHeaderName:mySecretValue'
)
Retrieve Webhook URL
const hook = await client.webhook.retrieve()
This will return the webhook URL for calls by Notarize.com - until the webhook is deleted, or changed to something else. The response will be something like:
{
"success": true,
"webhookUrl": "https://my.service.com/esign/callback"
}
Delete Webhook URL
const hook = await client.webhook.delete()
This will delete (clear) the webhook URL for any subsequent calls by Notarize.com - until the webhook is set. The response will be something like:
{
"success": true
}
Simulate Webhook Responses
const hook = await client.webhook.simulateResponses({
"event": "transaction_status_update",
"data": {
"transactionId": "jhkjhkjh",
"status": "received"
}
})
If a webhook is set, then this will send the provided data to the webhook URL for processing by your receiver code of the webhooks. This is simply a way to send test data through Notarize.com to your webhook receiver endpoint. The response will be something like:
{
"success": true
}
Development
For those interested in working on the library, there are a few things that
will make that job a little simpler. The organization of the code is all in
src/
, with one module per section of the Client: document
, template
,
etc. This makes location of the function very easy.
Additionally, the main communication with the Notarize service is in the
src/index.ts
module in the fire()
function. In the constructor for the
Client, each of the sections are created, and then they link back to the
main class for their communication work.
Setup
In order to work with the code, the development dependencies include dotenv
so that each user can create a .env
file with two values for working with
Notarize.com:
NOTARIZE_API_KEY
- this is the API Key referred to, above, and can be created on the Notarize website's API Keys pageNOTARIZE_TEST_EMAIL
- this is your email, or a test email, that will be used in all the tests intests/
so that you can easily control the destionation for the emails.
Testing
There are several test scripts that create, test, and tear-down, state on the Notarize.com service exercising different parts of the API. Each is self-contained, and can be run with:
$ npm run ts tests/update-transaction.ts
creating a new transaction...
Success!
updating the new transaction...
Success!
retrieving the updated transaction...
Success!
deleting the new transaction...
Success!
Each of the tests will run a series of calls through the Client, and check the
results to see that the operation succeeded. As shown, if the steps all
report back with Success!
then things are working.
If there is an issue with one of the calls, then an Error!
will be printed
out, and the data returned from the client will be dumped to the console.