This SDK is now deprecated and will no longer receive feature updates or bug fixes. Security fixes will still be applied as needed.
The new @dropbox/sign
SDK can be found at hellosign/dropbox-sign-node!
The new SDK and this legacy SDK are not backwards-compatible!
Please see here for a comprehensive migration guide.
A NodeJS / JavaScript wrapper for the HelloSign API
First time using npm? Read more about installing npm packages [here] (https://docs.npmjs.com/downloading-and-installing-packages-locally).
Install from npm:
# Optionally, to scaffold your package.json first
npm init
npm install hellosign-sdk
# Optionally, to install testing / development dependencies
cd node_modules/hellosign-sdk
npm install
Install from code:
git clone https://github.com/HelloFax/hellosign-nodejs-sdk.git
cd hellosign-nodejs-sdk
# install dependencies
npm install
In your Node application, require hellosign-sdk
(or the path to the sdk folder if not using npm) and pass authentication information to initialize it:
// Initialize using api key
var hellosign = require('hellosign-sdk')({key: 'YOUR API KEY HERE'});
OR
// Initialize using email and password
var hellosign = require('hellosign-sdk')({username: 'your_email_address', password: 'your_password'});
OR
// Initialize for embedded requests using your api key, client id, and (optionally, for OAuth) client secret
var hellosign = require('hellosign-sdk')({key: 'YOUR API KEY HERE', client_id: 'your client id', client_secret: 'your client secret'});
For initialization for Oauth app-specific calls, see the Oauth section below.
Each function in the SDK is called from your initialized hellosign object, followed by the module name, and then the method.
hellosign.template.list();
See below for a list of modules and their associated endpoint methods.
The results of each method can be accessed either as a callback, or a promise:
Callback style responses are included as the last (or only, in the case of no others) parameter in a call:
hellosign.signatureRequest.send({/*options*/}, function(err, response){
if (err) {
//do something with error
} else {
//parse response
}
});
Promise style access is through Javascript!
hellosign.signatureRequest.send({/*options*/})
.then(function(response){
//parse response
})
.catch(function(err){
//do something with error
})
.finally(function(){
//optionally do yet another thing
});
Returned promises are then-able, or can be returned for later resolution.
Modules in the SDK are as follows:
hellosign.account.get()
.then();
var new_callback_url = "https://www.example.com/callback"
hellosign.account.update({callback_url: new_callback_url})
.then();
var email: "new_user@example.com";
hellosign.account.create({
email_address: email
})
.then();
var email: "possibly_existing_user@example.com";
var account_id: '12738igfe87egqo22';
hellosign.account.verify({email_address: email,})
.then();
hellosign.account.verify({account_id: email,})
.then();
hellosign.signatureRequest.get("fa5c8a0b0f492d768749333ad6fcc214c111e967")
.then();
hellosign.signatureRequest.list()
.then(function(res){
console.log(res.signature_requests);
});
This endpoint can optionally receive the parameters page
, and page_size
, passed in as an options object:
hellosign.signatureRequest.list({page: 2, page_size: 15})
This endpoint can optionally be used to query and search for items such as page
, title
, and from
passed in as an options object:
const opts = {
page: 1,
query: 'title:Test +title AND from:me'
}
hellosign.signatureRequest.list(opts).then((res) => {
console.log(res);
}).catch((err) => {
console.error(err);
});
var signers = [
{
email_address : 'jack@example.com',
name : 'Jack',
order : 0,
sms_phone_number: '+14155550101',
},
{
email_address : 'jill@example.com',
name : 'Jill',
order : 1,
}
]
OR
// Any of the signers is eligible to sign for the entire group.
var signerGroup = [
{
group: 'Authorized signatory',
[0]: {
name: 'Jack',
email_address: 'jack@example.com'
},
[1]: {
name: 'Jill',
email_address: 'jill@example.com'
}
},
]
var options = {
test_mode : 1,
title : 'NDA with Acme Co.',
subject : 'The NDA we talked about',
message : 'Please sign this NDA and then we can discuss more. Let me know if you have any questions.',
signers : signers,
attachments: [
{
name: 'Example Name',
instructions: 'Example instructions',
signer_index: 1,
required: 1,
},
],
cc_email_addresses : ['lawyer@example.com', 'lawyer2@example.com'],
files : ['my/docs/nda.pdf'],
metadata : {
clientId : '1234',
custom_text : 'NDA #9'
}
};
hellosign.signatureRequest.send(options)
.then(function(res){
console.log(res.signature_request);
});
var signers = [
{
email_address : 'george@example.com',
name : 'George',
role : 'Signer'
}
]
OR
// Any of the signers is eligible to sign for the entire group.
var signerGroup = [
{
role: 'Signer',
group: 'Authorized signatory',
[0]: {
name: 'George',
email_address: 'george@example.com',
},
[1]: {
name: 'Gina',
email_address: 'gina@example.com',
}
},
]
var options = {
test_mode : 1,
template_id : '7b63c2131099ef7effeb0e980e2c42005fe3405d',
subject : 'Purchase Order',
message : 'Glad we could come to an agreement.',
signers : signers,
custom_fields: [
{
name: "start_date",
value: "01/10/2016",
editor: "Signer",
required: true
}
]
};
hellosign.signatureRequest.sendWithTemplate(options)
.then(function(res){
console.log(res.signature_request);
});
var request_id = 'fa5c8a0b0f492d768749333ad6fcc214c111e967'
var email = 'thedude@abides.com'
hellosign.signatureRequest.remind(request_id,{email_address : email})
.then(function(res){
console.log(res.signature_request);
});
const opts = {
signature_id: '35e3787bd2e61e496099',
email_address: 'mary@example.com',
}
hellosign.signatureRequest.update('2f9781e1a8e2045224d808c153c2e1d3df6f8f2f', opts).then((res) => {
console.log('what is the response?', res);
}).catch((err) => {
console.error('what is the error?', err);
});
var request_id = 'fa5c8a0b0f492d768749333ad6fcc214c111e967'
hellosign.signatureRequest.download(request_id, {file_type: 'zip'}, function(err, response) {
var file = fs.createWriteStream("files.zip");
response.pipe(file);
file.on('finish', function() {
file.close();
});
});
var request_id = 'fa5c8a0b0f492d768749333ad6fcc214c111e967';
hellosign.signatureRequest.cancel(request_id)
.then(function(response){
console.log(response.statusCode);
console.log(response.statusMessage);
})
.catch(function(err){
// Handle errors
});
See below for more info on the statusCode / statusMessage properties.
var request_id = 'fa5c8a0b0f492d768749333ad6fcc214c111e967';
hellosign.signatureRequest.removeAccess(request_id)
.then(function(response){
console.log(response.statusCode);
console.log(response.statusMessage);
})
.catch(function(err){
// Handle errors
});
See below for more info on the statusCode / statusMessage properties.
var options = {
test_mode : 1,
clientId : '0836272d66a1b53f9822f3aa07aef704',
title : 'NDA with Acme Co.',
subject : 'The NDA we talked about',
message : 'Please sign this NDA and then we can discuss more. Let me know if you have any questions.',
signers : [
{
email_address : 'jack@example.com',
name : 'Jack',
order : 0,
sms_phone_number: '+14155550101',
},{
email_address : 'jill@example.com',
name : 'Jill',
order : 1,
}
],
attachments: [
{
name: 'Example Name',
instructions: 'Example instructions',
signer_index: 1,
required: 1,
},
],
cc_email_addresses : ['lawyer@example.com', 'lawyer@example2.com'],
files : ['my/files/nda.pdf']
};
hellosign.signatureRequest.createEmbedded(options)
.then(function(res){
console.log(res.signature_request);
});
var options = {
test_mode : 1,
clientId : '0836272d66a1b53f9822f3aa07aef704',
template_id : '7b63c2131099ef7effeb0e980e2c42005fe3405d',
subject : 'Purchase Order',
message : 'Glad we could come to an agreement.',
signers : [
{
email_address : 'george@example.com',
name : 'George',
role : 'Signer'
}
]
};
hellosign.signatureRequest.createEmbeddedWithTemplate(options);
.then(function(res){
console.log(res.signature_request);
});
var request_id = 'fa5c8a0b0f492d768749333ad6fcc214c111e967';
hellosign.signatureRequest.releaseHold(request_id)
.then(function(response){
console.log(response);
})
.catch(function(err){
// Handle errors
});
var signature_id = 'fa5c8a0b0f492d768749333ad6fcc214c111e967';
hellosign.embedded.getSignUrl(signature_id)
.then();
// GET
var template_id = '7b63c2131099ef7effeb0e980e2c42005fe3405d';
hellosign.embedded.getEditUrl(template_id)
.then();
// POST
var template_id = '7b63c2131099ef7effeb0e980e2c42005fe3405d';
const opts = {
test_mode: 1,
merge_fields: [{"name":"Last Name","type":"text"}]
};
hellosign.embedded.postEditUrl(template_id, opts)
.then();
const opts = {
test_mode: 1,
start_date: '09/13/2020',
end_date: '09/20/2020',
report_type: ['user_activity', 'document_status']
};
client.reports.get(opts).then((res) => {
console.log('what is the response?', res);
}).catch((err) => {
console.error('what is the error?', err);
});
You'll need to create an API app, and add OAuth support, and then use the URL provided to authorize users for your application. When you do so, you'll get a state and code value that can be used as below to get an OAuth access token.
See our OAuth 2.0 walkthrough for more details.
var hellosign = require('./hellosign.js')({key: 'YOUR API KEY HERE', client_id: 'your client id', client_secret: 'your client secret'});
hellosign.oauth.getToken({state : '53b02619', code : '1d0219ea3363aa67'})
.then();
Use the access token to instantiate an app-specific HelloSign object:
var hellosignOauth = require('./hellosign-nodejs-sdk/lib/hellosign.js')({oauthToken: 'YOUR_ACCESS_TOKEN'});
You can then use the HelloSign object you've created with the Oauth key to perform requests with that key:
var options = {
test_mode : 1,
title : 'NDA with Acme Co.',
subject : 'The NDA we talked about',
message : 'Please sign this NDA and then we can discuss more. Let me know if you have any questions.',
signers : [
{
email_address : 'jack@example.com',
name : 'Jack',
order : 0
},
{
email_address : 'jill@example.com',
name : 'Jill',
order : 1
}
],
cc_email_addresses : ['lawyer@example.com', 'lawyer@example2.com'],
files : ['nda.pdf']
};
hellosignOauth.signatureRequest.send(options)
.then();
From the HelloSign instance with your app's client_id and secret set, you can also use the refresh token you got in the first token call above to fetch a new access token for your use:
hellosign.oauth.refreshToken({refresh_token : 'YOUR_REFRESH_TOKEN'})
.then();
hellosign.team.get()
.then(function(res){
console.log(res.team);
});
var team_name = 'Radion 6'
hellosign.team.create({name: team_name})
.then(function(res){
console.log(res.team);
});
var newName = 'The Mr. T Team';
hellosign.team.update({name: newName})
.then(function(res){
console.log(res.team);
});
hellosign.team.destroy().then((res) => {
console.log('what is the statusCode?', res.statusCode);
console.log('what is the statusMessage?', res.statusMessage);
}).catch((err) => {
console.error('what is the error?', err);
});
var memberEmail = 'benedict@cumberbatch.org';
hellosign.team.addMember({email_address: memberEmail})
.then(function(res){
console.log(res.team);
});
var memberEmail = 'benedictinemonk@cumberbatch.org';
hellosign.team.removeMember({email_address: memberEmail})
.then(function(res){
console.log(res.team);
});
hellosign.template.list();
.then(function(res){
console.log(res.templates);
}
var template_id = '7b63c2131099ef7effeb0e980e2c42005fe3405d';
hellosign.template.get(template_id)
.then(function(res){
console.log(res.template);
});
var template_id = '7b63c2131099ef7effeb0e980e2c42005fe3405d';
var memberEmail = 'robin@batman.com'
hellosign.template.addUser(
template_id,
{
email_address: memberEmail
}
)
.then(function(res){
console.log(res.template);
});
var template_id = '7b63c2131099ef7effeb0e980e2c42005fe3405d';
var memberEmail = 'othersidekick@batman.com'
hellosign.template.removeUser(
template_id,
{
email_address: memberEmail
}
)
.then(function(res){
console.log(res.template);
});
var options = {
test_mode: 1,
files: ['my/files/nda.pdf'],
title: 'embedded draft test',
subject: 'embedded draft test',
message: 'embedded draft test',
signer_roles: [
{
name: 'Sherlock',
order: 0
},{
name: 'Watson',
order: 1
}
],
cc_roles: ['commissioner@metropolice.gov.uk']
};
var results = hellosign.template.createEmbeddedDraft(options)
.then(function(res){
console.log(res.template);
});
hellosign.template.delete(templateId)
.then(function(res){
console.log(response.statusCode);
console.log(response.statusMessage);
})
hellosign.unclaimedDraft.create({
test_mode : 1,
files : ['my/files/nda.pdf', 'other/files/secret.pdf']
})
.then(function(res){
console.log(res.unclaimed_draft.claim_url);
});
var options = {
test_mode : 1,
clientId : '0836272d66a1b53f9822f3aa07aef704',
type : 'request_signature',
subject : 'The NDA we talked about',
requester_email_address : 'jack@hellosign.com',
files : ['my/secret/lair/nda.pdf'],
is_for_embedded_signing : 1
};
hellosign.unclaimedDraft.createEmbedded(options)
.then(function(res){
console.log(res.unclaimed_draft.claim_url);
});
var options = {
test_mode: 1,
template_id: '7b63c2131099ef7effeb0e980e2c42005fe3405d',
title: 'embedded draft test',
subject: 'embedded draft test',
message: 'embedded draft test',
signing_redirect_url: 'http://bondstreet.co.uk',
requesting_redirect_url: 'http://met.police.uk',
signers: [
{
name: 'Sherlock',
role: 'Signer',
email_address: 'sherlock@holmesdetective.co.uk',
pin: 3645
},{
name: 'Watson',
role: 'Assistant',
email_address: 'watson@holmesdetective.co.uk',
pin: 4657
}
],
attachments: [
{
name: 'Example Name',
instructions: 'Example instructions',
signer_index: 1,
required: 1,
},
],
requester_email_address: 'mrshudson@landlady.com',
metadata: {
clue1: 'pink suitcase',
clue2: 'rache...'
}
};
hellosign.unclaimedDraft.createEmbeddedWithTemplate(options);
.then(function(res){
console.log(res.unclaimed_draft.claim_url);
});
var options = {
test_mode: 1,
clientId: 'b6b8e7deaf8f0b95c029dca049356d4a2cf9710a'
};
hellosign.unclaimedDraft.editAndResend('2f9781e1a83jdja934d808c153c2e1d3df6f8f2f', opts)
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
});
hellosign.apiApp.get(clientId).then((res) => {
// handle response
}).catch((err) => {
// handle error
});
hellosign.apiApp.list().then((res) => {
// handle response
}).catch((err) => {
// handle error
});
const opts = {
name: 'My Cool App',
domain: 'http://www.example.com',
callback_url: 'http://www.example.com/callback',
white_labeling_options: '{"primary_button_color":"#ff0000","primary_button_text_color":"#000000"}'
};
hellosign.apiApp.create(opts).then((res) => {
// handle response
}).catch((err) => {
// handle error
});
const opts = {
name: 'My Cool App',
domain: 'http://www.example.com',
white_labeling_options: '{"primary_button_color":"#ff0000","primary_button_text_color":"#000000"}'
};
hellosign.apiApp.update(clientId, opts).then((res) => {
// handle response
}).catch((err) => {
// handle error
});
hellosign.apiApp.delete(clientId).then((res) => {
console.log('what is the statusCode?', res.statusCode);
console.log('what is the statusMessage?', res.statusMessage);
}).catch((err) => {
console.error('what is the error?', err);
});
Any warnings returned from the api will be accessible on the response object returned:
hellosign.account.get()
.then(function(res){
console.log(res.warnings);
});
On any response object, you can inspect the statusCode
and statusMessage
properties to get HTTP status information.
This is especially useful for endpoints that don't return any JSON information, like cancel
:
hellosign.signatureRequest.cancel('fa5c8a0b0a492d768749333ad6fcc214c111e967')
.then(function(response){
console.log(response.statusCode);
console.log(response.statusMessage);
});
Unit tests can be run simply by executing:
npm test
Mocked functional tests are coming soon. Look inside the repo for a sneak peak.
We do not allow app callbacks (event or OAuth) to be set to localhost. However it is still possible to test callbacks against a local server. Tunneling services such as ngrok (http://ngrok.com) can help you set this up.
The MIT License (MIT)
Copyright (C) 2020 hellosign.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.