Node Migration Guide

Migrating the Node SDK from hellosign-sdk to @dropbox/sign

Welcome! Dropbox Sign's new Node SDK is generated from our officially maintained OpenAPI spec. In this release, we've made important updates that introduce new functionality and create feature parity between the Dropbox Sign API and the Node SDK. However, some of these changes are considered "breaking" in the sense that they'll require you to update your existing code in order to continue using the SDK.

In this migration guide, we'll cover core concepts in the new SDK, highlight differences from legacy versions, and provide example code showing how past implementations map to the new version's syntax. We'll link out to supporting documents that offer more context behind the breaking changes and why we made them. We apologize for any inconvenience these changes may cause, but are confident the new features will add value to your integration.

Remember that we are here to help if you have any questions or need assistance along the way. Thank you for using Dropbox Sign's Node SDK. We hope you enjoy the improvements!

Architecture and Tooling

As mentioned above, the new Node SDK (@dropbox/sign) is generated from our OpenAPI Spec. Some of the architectural changes impact the tools and locations you use to interact with the SDK.

SDK Resources

  • Download -- using this new npm repo. New Node SDK versions will now be published here.
  • Development -- active development against the Node SDK happens here: hellosign-openapi/sdks/node.
  • SDK GitHub Repo -- dropbox-sign-node is updated based on changes to hellosign-openapi/sdks/node, but no active development work happens there.
  • Reference Docs -- the automatically generated Reference Docs are a great way to explore the SDK.
  • Examples -- our full suite of ready to use examples will help you get started quickly.
  • Engagement -- use the OpenAPI repo to submit Issues or Pull Requests for the Node SDK.

Core Concepts and Patterns

This section contains the core concepts and patterns of the new SDK and highlights differences from the legacy SDK.

Installation

There are two methods for installing the new SDK:

Install from NPM

  1. Optionally, to scaffold your package.json first run:
    npm init
  2. To install from NPM run:
    npm install @dropbox/sign

Build from Source

  1. Clone the repo locally
    git clone https://github.com/hellosign/dropbox-sign-node.git
  2. Run npm pack
  3. Move generated file (dropbox-sign-1.0.0.tgz or similar) to your project directory
  4. In the dependencies array of your package.json file, add
    "@dropbox/sign": "file:dropbox-sign-1.0.0.tgz"
  5. Run npm install

Importing the SDK

The new Node SDK is packaged as an ES Module rather than CommonJS, which means you'll bring it into your code base differently.

Legacy Node SDK

Use require statement to bring in the entire Dropbox Sign SDK.

New Node SDK

Use import statement to add the entire SDK or only the pieces you need.

Legacy SDK - requireNew SDK - import
Copy
Copied
const sign_sdk = require('hellosign-sdk')({ key: "API_KEY" });
Copy
Copied
// Add entire SDK
import * as DropboxSign from "@dropbox/sign";

// or add only what you need
import { SignatureRequestApi } from "@dropbox/sign";

const signatureApi = new SignatureRequestApi();
warning
To support ES Modules and use import statements in your Node project, your package.json file must contain "type": "module".

Authentication

Rather than one big SDK with access to everything, the new Node SDK is organized into groups of similar endpoints.

Legacy Node SDK

Pass credentials once when instantiating the SDK.

New Node SDK

Pass credentials each time a new section of the SDK is instantiated (Signature Request, Template, Account, etc.)

Legacy SDK - AuthenticationNew SDK - Authentication with API KeyNew SDK - Authentication with OAuth Token
Copy
Copied
const sign_sdk = require('hellosign-sdk')({key: 'YOUR API KEY HERE'});
Copy
Copied
import { SignatureRequestApi, AccountApi } from "@dropbox/sign";

const signatureApi = new SignatureRequestApi();
signatureApi.username = "YOUR_API_KEY";

const accountApi = new AccountApi();
accountApi.username = "YOUR_API_KEY";
Copy
Copied
import { SignatureRequestApi, AccountApi } from "@dropbox/sign";

const signatureApi = new SignatureRequestApi();
signatureApi.accessToken = "YOUR_ACCESS_TOKEN";

const accountApi = new AccountApi();
accountApi.accessToken = "YOUR_ACCESS_TOKEN";

Endpoints Grouped into Classes

The new SDK divides endpoints across unique Classes:

Class Name and ReferenceAPI Reference
AccountApi/account/* Endpoints
ApiAppApi/api_app/* Endpoints
BulkSendJobApi/bulk_send_job/* Endpoints
EmbeddedApi/embedded/* Endpoints
OAuthApi/oauth/* Endpoints
ReportApi/report/* Endpoints
SignatureRequestApi/signature_request/* Endpoints
TeamApi/team/* Endpoints
TemplateApi/template/* Endpoints
UnclaimedDraftApi/unclaimed_draft/* Endpoints

Using Models to Pass Parameters

Models are used to define the structure and value of the parameters being passed. The fully assembled model is passed to the API endpoint method.

New SDK Using Models to Pass Parameters

Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const fs = require('fs');

const apiAppApi = new DropboxSign.ApiAppApi();

apiAppApi.username = "YOUR_API_KEY";

const oauth = {
  callbackUrl: "https://example.com/oauth",
  scopes: [
    "basic_account_info",
    "request_signature"
  ]
};

const whiteLabelingOptions = {
  primaryButtonColor: "#00b3e6",
  primaryButtonTextColor: "#ffffff"
};

const data = {
  name: "My Production App",
  domains: ["example.com"],
  customLogoFile: fs.createReadStream("CustomLogoFile.png"),
  oauth,
  whiteLabelingOptions
};

const result = apiAppApi.apiAppCreate(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Path and Query Parameters

When passing parameters to the API methods in the legacy SDK it was standard to pass the parameters inside of an object to the API method. For example using the opts object below:

Legacy SDK - Path and Query Parameters

Copy
Copied
const hellosign = require('hellosign-sdk')({ key: 'HelloSign_API_KEY' });

const opts = {
  page: 1,
  account_id: 'all'
}

hellosign.signatureRequest.list(opts).then((res) => {
  console.log(res);
}).catch((err) => {
  console.error(err);
});
The new SDK no longer accepts objects when passing path or query parameters to endpoints. Instead you will need to pass the parameters as separate variables such as accountId and page below:

New SDK - Path and Query Parameters

Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureApi = new DropboxSign.SignatureRequestApi();
signatureApi.username = "YOUR_API_KEY";

const accountId = null;
const page = 1;

const result = signatureApi.signatureRequestList(accountId, page);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Endpoints that have both path or query parameters, and accept POST data, will have a mix of both styles:

New SDK - Path, Query, and Post Data with JavascriptNew SDK - Path, Query, and Post Data with TypeScript
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureRequestApi = new DropboxSign.SignatureRequestApi();

signatureRequestApi.username = "YOUR_API_KEY";

const data = {
  emailAddress: "john@example.com"
};

const signatureRequestId = "2f9781e1a8e2045224d808c153c2e1d3df6f8f2f";

const result = signatureRequestApi.signatureRequestRemind(signatureRequestId, data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureRequestApi = new DropboxSign.SignatureRequestApi();

signatureRequestApi.username = "YOUR_API_KEY";

const data: DropboxSign.SignatureRequestRemindRequest = {
  emailAddress: "john@example.com"
};

const signatureRequestId = "2f9781e1a8e2045224d808c153c2e1d3df6f8f2f";

const result = signatureRequestApi.signatureRequestRemind(signatureRequestId, data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Error Handling and Warnings

The New SDK handles errors and warnings differently.

Error Handling

Errors are an instance of HttpError with its body parameter being an instance of ErrorResponse class and should be handled using Try/Catch blocks.
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const accountApi = new DropboxSign.AccountApi();

accountApi.username = "YOUR_API_KEY";

const data = {
  emailAddress: "newuser@dropboxsign.com"
};

const result = accountApi.accountCreate(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  // error is instance of HttpError
  console.log("Exception when calling Dropbox Sign API:");
  // error.body is instance of ErrorResponse
  console.log(error.body);
});

Warnings

Warnings are a list of WarningResponse.

New SDK - Warnings

Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const accountApi = new DropboxSign.AccountApi();

accountApi.username = "YOUR_API_KEY";

const data = {
  emailAddress: "newuser@dropboxsign.com"
};

const result = accountApi.accountCreate(data);
result.then(response => {
  console.log(response.body);

  // warning loop
  response.body.warnings.forEach(warning => {
    console.log(`Warning Name: ${warning.warningName}`);
    console.log(`Warning Message: ${warning.warningMsg}`);
  });
}).catch(error => {
  // error is instance of HttpError
  console.log("Exception when calling Dropbox Sign API:");
  // error.body is instance of ErrorResponse
  console.log(error.body);
});

Instantiating Objects From Data

There are two ways to instantiate an object.

  • You can instantiate a class directly and use setters to set your data
  • You can use an object literal that matches expected type definitions
New SDK - Using SettersNew SDK - Using Object Literal
Copy
Copied
const signer1 = new DropboxSign.SubSignatureRequestSigner();
signer1.name = "George";
signer1.emailAddress = "george@example.com";

const attachment1 = new DropboxSign.SubAttachment();
attachment1.name = "Attachment 1";
attachment1.instructions = "Please download this file";
attachment1.signerIndex = 0;
attachment1.required = true;
Copy
Copied
// with optional TypeScript type
const signer1: DropboxSign.SubSignatureRequestSigner = {
  name: "George",
  emailAddress: "george@example.com"
};

// with optional TypeScript type
const attachment1: DropboxSign.SubAttachment = {
  name: "Attachment 1",
  instructions: "Please download this file",
  signerIndex: 0,
  required: true
};

Event Callback Helper

A callback helper class is included in the New SDK repo to assist in verifying callbacks. The helper simplifies:

  1. Checking event authenticity with built in event hash check
  2. Displaying event types (account callback vs. app callback)
  3. Displaying event messages
The EventCallbackHelper and EventCallbackRequest classes facilitate parsing of event data and assist in validating that a callback originated from Dropbox Sign.We will send event callback payloads to you as a multipart/form-data request with a single json formfield that contains your event callback as a JSON string.

Example Event Callback Request From US to YOU

Copy
Copied
curl -X POST 'https://example.com/YOUR_EVENT_CALLBACK_URL' \
  -F 'json={"event":{"event_type":"account_confirmed","event_time":"1669926463","event_hash":"ff8b03439122f9160500c3fb855bdee5a9ccba5fff27d3b258745d8f3074832f","event_metadata":{"related_signature_id":null,"reported_for_account_id":"6421d70b9bd45059fa207d03ab8d1b96515b472c","reported_for_app_id":null,"event_message":null}}}'

Example JSON Payload

Copy
Copied
{
  "event": {
    "event_type": "account_confirmed",
    "event_time": "1669926463",
    "event_hash": "ff8b03439122f9160500c3fb855bdee5a9ccba5fff27d3b258745d8f3074832f",
    "event_metadata": {
      "related_signature_id": null,
      "reported_for_account_id": "6421d70b9bd45059fa207d03ab8d1b96515b472c",
      "reported_for_app_id": null,
      "event_message": null
    }
  }
}

How to use the EventCallbackHelper

Copy
Copied
import { EventCallbackRequest, EventCallbackHelper } from "@dropbox/sign";

// use your API key
const api_key = '324e3b0840f065eb51f3fd63231d0d33daa35d4ed10d27718839e81737065782';

// callback_data represents data we send to you
const callback_data = JSON.parse(req.body.json);

const callback_event = EventCallbackRequest.init(callback_data);

// verify that a callback came from HelloSign.com
if (EventCallbackHelper.isValid(api_key, callback_event)) {
  // one of "account_callback" or "api_app_callback"
  const callback_type = EventCallbackHelper.getCallbackType(callback_event);

  // do your magic below!
}

Native TypeScript Support

The new SDK is written in TypeScript and comes fully typed for the best possible developer experience.

If you do not use TypeScript you can still use the new SDK as normal.


Differences from Legacy SDK

This section highlights larger changes to be aware of when migrating to the new SDK.

Form Fields Per Document

The Form Fields per Document parameter has changed from a two dimensional array, to a one dimensional array—allowing you to designate which file you to add the field to using documentIndex. You can learn more about this change here: Form Fields per Document.
Legacy SDK - Form Fields Per DocumentNew SDK - Form Fields Per Document
Copy
Copied
const hellosign = require('hellosign-sdk')({ key: process.env.HelloSign_API_KEY });

module.exports = {
send_signature_request: function () {
  const opts = {
    test_mode: 1,
    files: ['Demo-Mutual-Non-Disclosure-Agreement.pdf'],
    title: 'NDA with Acme Co.',
    subject: 'The NDA we talked about',
    message: 'Please sign this NDA and then we can discuss more.',
    signers: [
      {
        name: 'Jill',
        email_address: 'jill@example.com'
      }
    ],
    form_fields_per_document: [[{
      "api_id": "abcd",
      "name": "signer_signature",
      "type": "signature",
      "x": 200,
      "y": 300,
      "page": 1,
      "width": 280,
      "height": 72,
      "required": true,
      "signer": 0
    }]]
};

  hellosign.signatureRequest.send(opts).then((res) => {
      console.log(res)
    }).catch((err) => {
      console.log(err)
    });
  }
}
Copy
Copied
import * as DropboxSign from "@dropbox/sign";
const fs = require('fs');

const signatureApi = new DropboxSign.SignatureRequestApi();
signatureApi.username = "YOUR_API_KEY";

const yourFile = fs.createReadStream('./Demo-Mutual-Non-Disclosure-Agreement.pdf');

const signer1 = {
  emailAddress: "Jack@example.com",
  name: "Jack",
  order: 0
};

const data = {
  testMode: true,
  files: [yourFile],
  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: [ signer1 ],
  formFieldsPerDocument: [
    {
      documentIndex: 0,
      apiId: "abcd",
      name: "signer_signature",
      type: "signature",
      x: 200,
      y: 300,
      page: 1,
      width: 280,
      height: 72,
      required: true,
      signer: "0"
    }
  ]
};

const result = signatureApi.signatureRequestSend(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Instantiating the Correct Field Class

There are several different types of form fields you can define, identified by the value of the type field and a few ways to instantiate the correct object when making an API request.

The different classes for each type are:

Field TypeClass
checkboxSubFormFieldsPerDocumentCheckbox
checkbox-mergeSubFormFieldsPerDocumentCheckboxMerge
date_signedSubFormFieldsPerDocumentDateSigned
dropdownSubFormFieldsPerDocumentDropdown
hyperlinkSubFormFieldsPerDocumentHyperlink
initialsSubFormFieldsPerDocumentInitials
radioSubFormFieldsPerDocumentRadio
signatureSubFormFieldsPerDocumentSignature
textSubFormFieldsPerDocumentText
text-mergeSubFormFieldsPerDocumentTextMerge

You can use a literal object definition with no typing:

New SDK - Form Fields Per Document Literal SignatureNew SDK - Form Fields Per Document Literal Text
Copy
Copied
const data = {
  testMode: true,
  files: [ yourFile ],
  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: [ signer1 ],
  formFieldsPerDocument: [
    {
      type: "signature",
      documentIndex: 0,
      apiId: "abcd",
      name: "field_1",
      x: 200,
      y: 300,
      page: 1,
      width: 280,
      height: 72,
      required: true,
      signer: "0"
    }
  ]
};
Copy
Copied
const data = {
  testMode: true,
  files: [ yourFile ],
  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: [ signer1 ],
  formFieldsPerDocument: [
    {
      type: "text",
      documentIndex: 0,
      apiId: "abcd",
      name: "field_1",
      x: 200,
      y: 300,
      page: 1,
      width: 280,
      height: 72,
      required: true,
      signer: "0",
      placeholder: "Fill me in!",
      masked: false
    }
  ]
};
You can also instantiate an instance of the correct class. In this scenario the type field is automatically set to the correct value for you:
New SDK - Form Fields Per Document Instance SignatureNew SDK - Form Fields Per Document Instance Text
Copy
Copied
// type is automatically set to "signature"
const formField1 = new DropboxSign.SubFormFieldsPerDocumentSignature();
formField1.documentIndex = 0;
formField1.apiId = "abcd";
formField1.name = "signer_signature";
formField1.x = 200;
formField1.y = 300;
formField1.page = 1;
formField1.width = 280;
formField1.height = 72;
formField1.required = true;
formField1.signer = "0";

const data = {
  testMode: true,
  files: [ yourFile ],
  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: [ signer1 ],
  formFieldsPerDocument: [ formField1 ]
};
Copy
Copied
// type is automatically set to "text"
const formField1 = new DropboxSign.SubFormFieldsPerDocumentText();
formField1.documentIndex = 0;
formField1.apiId = "abcd";
formField1.name = "signer_signature";
formField1.x = 200;
formField1.y = 300;
formField1.page = 1;
formField1.width = 280;
formField1.height = 72;
formField1.required = true;
formField1.signer = "0";
formField1.placeholder = "Fill me in!";
formField1.masked = false;

const data = {
  testMode: true,
  files: [ yourFile ],
  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: [ signer1 ],
  formFieldsPerDocument: [ formField1 ]
};

If you are using TypeScript you can use a literal object definition with typehint on the object itself. If you use a typehint any invalid or missing data will be highlighted on the object itself in your IDE.

If you use TypeScript but do not typehint the object, you will see the error when passing the data to the API endpoint.

New SDK - Form Fields Per Document with Typescript TypehintedNew SDK - Form Fields Per Document with Typescript NOT Typehinted
Copy
Copied
// TS2741: Property '"type"' is missing in type [...]
const formField1: DropboxSign.SubFormFieldsPerDocumentSignature = {
  documentIndex: 0,
  apiId: "abcd",
  name: "field_1",
  x: 200,
  y: 300,
  page: 1,
  width: 280,
  height: 72,
  required: true,
  signer: "0"
}

const data = {
  testMode: true,
  files: [ yourFile ],
  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: [ signer1 ],
  formFieldsPerDocument: [ formField1 ]
};

const result = signatureApi.signatureRequestSend(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});
Copy
Copied
const formField1 = {
  documentIndex: 0,
  apiId: "abcd",
  name: "field_1",
  x: 200,
  y: 300,
  page: 1,
  width: 280,
  height: 72,
  required: true,
  signer: "0"
}

const data = {
  testMode: true,
  files: [ yourFile ],
  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: [ signer1 ],
  formFieldsPerDocument: [ formField1 ]
};

// TS2345: Argument of type [...]
const result = signatureApi.signatureRequestSend(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

"role" Value in signers Object

In the Legacy SDK when making a Signature Request using a Template the signers property was an object with the role name as the key. In the new SDK the role value has been moved into the signer object itself.For example for the /signature_request/send_with_template endpoint the signers property could be represented as:
Legacy SDK - signers with RolesNew SDK - signers with Roles
Copy
Copied
{
  "signers": {
    "Client": {
      "name": "George",
      "email_address": "george@example.com"
    },
    "Manager": {
      "name": "Bob",
      "email_address": "bob@example.com"
    }
  }
}
Copy
Copied
{
  "signers": [
    {
      "role": "Client",
      "name": "George",
      "email_address": "george@example.com"
    },
    {
      "role": "Manager",
      "name": "Bob",
      "email_address": "bob@example.com"
    }
  ]
}

Using the new SDK you would now send this data as follows:

New SDK - signers with Roles Example #1New SDK - signers with Roles Example #2
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureRequestApi = new DropboxSign.SignatureRequestApi();

signatureRequestApi.username = "YOUR_API_KEY";

const data = {
  templateIds: ["c26b8a16784a872da37ea946b9ddec7c1e11dff6"],
  subject: "Purchase Order",
  message: "Glad we could come to an agreement.",
  signers: [
    {
      "role": "Client",
      "name": "George",
      "emailAddress": "george@example.com"
    },
    {
      "role": "Manager",
      "name": "Bob",
      "emailAddress": "bob@example.com"
    }
  ]
};

const result = signatureRequestApi.signatureRequestSendWithTemplate(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureRequestApi = new DropboxSign.SignatureRequestApi();

signatureRequestApi.username = "YOUR_API_KEY";

const signer1 = {
  role: "Client",
  name: "George",
  emailAddress: "george@example.com"
};

const signer2 = {
  role: "Manager",
  name: "Bob",
  emailAddress: "bob@example.com"
};

const data = {
  templateIds: ["c26b8a16784a872da37ea946b9ddec7c1e11dff6"],
  subject: "Purchase Order",
  message: "Glad we could come to an agreement.",
  signers: [ signer1, signer2 ]
};

const result = signatureRequestApi.signatureRequestSendWithTemplate(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

"role" Value in ccs Property

In the Legacy SDK when making a Signature Request using a Template the ccs property was an object with the role name as the key. In the new SDK the role value has been moved into the cc object itself, alongside a new email_address property.For example for the /signature_request/send_with_template endpoint the ccs property could be represented as:
Legacy SDK - ccsNew SDK - ccs
Copy
Copied
{
  "ccs": {
    "Client": "george@example.com",
    "Manager": "bob@example.com"
  }
}
Copy
Copied
{
  "ccs": [
    {
      "role": "Client",
      "email_address": "george@example.com"
    },
    {
      "role": "Manager",
      "email_address": "bob@example.com"
    }
  ]
}

Using the new SDK you would now send this data as follows:

New SDK - ccs Example #1New SDK - ccs Example #2
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureRequestApi = new DropboxSign.SignatureRequestApi();

signatureRequestApi.username = "YOUR_API_KEY";

const data = {
  templateIds: ["c26b8a16784a872da37ea946b9ddec7c1e11dff6"],
  subject: "Purchase Order",
  message: "Glad we could come to an agreement.",
  signers: [
    {
      role: "Client",
      name: "George",
      emailAddress: "george@example.com"
    },
    {
      role: "Manager",
      name: "Bob",
      emailAddress: "bob@example.com"
    }
  ],
  ccs: [
    {
      role: "Client",
      emailAddress: "george@example.com"
    },
    {
      role: "Manager",
      emailAddress: "bob@example.com"
    }
  ]
};

const result = signatureRequestApi.signatureRequestSendWithTemplate(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureRequestApi = new DropboxSign.SignatureRequestApi();

signatureRequestApi.username = "YOUR_API_KEY";

const signer1 = {
  role: "Client",
  name: "George",
  emailAddress: "george@example.com"
};

const signer2 = {
  role: "Manager",
  name: "Bob",
  emailAddress: "bob@example.com"
};

const cc1 = {
  role: "Client",
  emailAddress: "george@example.com"
};

const cc2 = {
  role: "Manager",
  emailAddress: "bob@example.com"
};

const data = {
  templateIds: ["c26b8a16784a872da37ea946b9ddec7c1e11dff6"],
  subject: "Purchase Order",
  message: "Glad we could come to an agreement.",
  signers: [ signer1, signer2 ],
  ccs: [ cc1, cc2 ]
};

const result = signatureRequestApi.signatureRequestSendWithTemplate(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

"name" Value in custom_fields Property

In the Legacy SDK when making a Signature Request with the custom_fields property it was an object with the name as the key. In the new SDK the name value has been moved into the custom_field object itself.For example for the /signature_request/send_with_template endpoint the custom_fields property could be represented as:
Legacy SDK - custom_fieldsNew SDK - custom_fields
Copy
Copied
{
  "custom_fields": {
    "company": {
      "value": "ABC Corp",
      "required": true
    }
  }
}
Copy
Copied
{
  "custom_fields": [
    {
      "name": "company",
      "value": "ABC Corp",
      "required": true
    }
  ]
}

Using the new SDK you would now send this data as follows:

New SDK - custom_fields Example #1New SDK - custom_fields Example #2
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureRequestApi = new DropboxSign.SignatureRequestApi();

signatureRequestApi.username = "YOUR_API_KEY";

const data = {
  templateIds: ["c26b8a16784a872da37ea946b9ddec7c1e11dff6"],
  subject: "Purchase Order",
  message: "Glad we could come to an agreement.",
  signers: [
    {
      role: "Client",
      name: "George",
      emailAddress: "george@example.com"
    },
    {
      role: "Manager",
      name: "Bob",
      emailAddress: "bob@example.com"
    }
  ],
  customFields: [
    {
      name: "company",
      value: "ABC Corp",
      required: true
    }
  ]
};

const result = signatureRequestApi.signatureRequestSendWithTemplate(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureRequestApi = new DropboxSign.SignatureRequestApi();

signatureRequestApi.username = "YOUR_API_KEY";

const signer1 = {
  role: "Client",
  name: "George",
  emailAddress: "george@example.com"
};

const signer2 = {
  role: "Manager",
  name: "Bob",
  emailAddress: "bob@example.com"
};

const customField1 = {
  name: "company",
  value: "ABC Corp",
  required: true
}

const data = {
  templateIds: ["c26b8a16784a872da37ea946b9ddec7c1e11dff6"],
  subject: "Purchase Order",
  message: "Glad we could come to an agreement.",
  signers: [ signer1, signer2 ],
  customFields: [ customField1 ]
};

const result = signatureRequestApi.signatureRequestSendWithTemplate(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

template_id to template_ids

The template_id parameter has been removed. You must now use template_ids.
Legacy SDK versionNew SDK Version
Template ID (template_id) is passed as a singular string:
template_id : "1234567890"
Template ID is passed as an array of strings (templateIds):
templateIds: ["1234567890"]

file to files

The file parameter has been renamed to files. Usage remains the same.

file_url to file_urls

The file_url parameter has been renamed to file_urls. Usage remains the same.

snake_case to camelCase

The variables, properties, and functions in the Legacy SDK were written in snake_case. The New SDK now uses camelCase instead, as this is what is standard practice for Node.
Legacy SDK - ParametersNew SDK - Parameters
Copy
Copied
test_mode
template_id
custom_fields
form_fields_per_document
signing_options
Copy
Copied
testMode
templateId
customFields
formFieldsPerDocument
signingOptions

Interacting with Files

The new SDK version introduces some new patterns around uploading and downloading files. You can read about them more in depth here: Interacting with Files.

Uploading Files

Passing a file with with your API request using the files parameter is different:
Legacy SDK versionNew SDK Version
Accepts a file binary or a path to a local fileOnly accepts a file binary
Legacy SDK - Files ParameterNew SDK - File Parameter
Copy
Copied
const hellosign = require('hellosign-sdk')({ key: process.env.HelloSign_API_KEY });

module.exports = {
send_signature_request: function () {
  const opts = {
    test_mode: 1,
    files: ['Demo-Mutual-Non-Disclosure-Agreement.pdf'],
    title: 'NDA with Acme Co.',
    subject: 'The NDA we talked about',
    message: 'Please sign this NDA and then we can discuss more.',
    signers: [
      {
        name: 'Jill',
        email_address: 'jill@example.com'
      }
    ]
  };

  hellosign.signatureRequest.send(opts).then((res) => {
    console.log(res)
  }).catch((err) => {
    console.log(err)
  });
 }
}
Copy
Copied
import * as DropboxSign from "@dropbox/sign";
const fs = require('fs');

const signatureApi = new DropboxSign.SignatureRequestApi();
signatureApi.username = "YOUR_API_KEY";

const yourFile = fs.createReadStream('./Demo-Mutual-Non-Disclosure-Agreement.pdf');

const signer1 = {
  emailAddress: "Jack@example.com",
  name: "Jack",
  order: 0
};

const data = {
  testMode: true,
  files: [ yourFile ],
  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: [ signer1 ]
};

const result = signatureApi.signatureRequestSend(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Downloading Files

Download functionality is now spread across multiple endpoints.

Legacy SDK VersionNew SDK version
Download Files is a single endpoint and the return is configured by parameters.Download Files spread across three endpoints
Legacy SDK - Download FilesNew SDK - Download Files
Copy
Copied
var signature_request_id = 'SIGNATURE_REQUEST_ID'

hellosign.signatureRequest.download(signature_request_id, {file_type: 'zip'}, function(err, response) {
var file = fs.createWriteStream("files.zip");
response.pipe(file);
  file.on('finish', function() {
    file.close();
  });
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureApi = new DropboxSign.SignatureRequestApi();
signatureApi.username = "YOUR_API_KEY";

const signatureRequestId = "SIGNATURE_REQUEST_ID";

const result = signatureApi.signatureRequestFiles(signatureRequestId);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});
Legacy SDK - Download Files as Data URINew SDK - Download Files as Data URI
Copy
Copied
var signature_request_id = 'SIGNATURE_REQUEST_ID'

hellosign.signatureRequest.download('SIGNATURE_REQUEST_ID', { get_data_uri: true }, (err, res) => {
 console.log(res)
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureApi = new DropboxSign.SignatureRequestApi();
signatureApi.username = "YOUR_API_KEY";

const signatureRequestId = "SIGNATURE_REQUEST_ID";

const result = signatureApi.signatureRequestFilesAsDataUri(signatureRequestId);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});
Legacy SDK - Download Files as File URLNew SDK - Download Files as File URL
Copy
Copied
var signature_request_id = 'SIGNATURE_REQUEST_ID'

hellosign.signatureRequest.download('SIGNATURE_REQUEST_ID', { get_url: true }, (err, res) => {
 console.log(res)
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureApi = new DropboxSign.SignatureRequestApi();
signatureApi.username = "YOUR_API_KEY";

const signatureRequestId = "SIGNATURE_REQUEST_ID";

const result = signatureApi.signatureRequestFilesAsFileUrl(signatureRequestId);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Downloading Templates

New SDK - Download Template FilesNew SDK - Template File as Data UriNew SDK - Template File as File Url
Copy
Copied
import * as DropboxSign from "@dropbox/sign";
import * as fs from 'fs';

const templateApi = new DropboxSign.TemplateApi();

// Configure HTTP basic authorization: api_key
templateApi.username = "YOUR_API_KEY";

// or, configure Bearer (JWT) authorization: oauth2
// templateApi.accessToken = "YOUR_ACCESS_TOKEN";

const templateId = "5de8179668f2033afac48da1868d0093bf133266";
const fileType = "pdf";

const result = templateApi.templateFiles(templateId, fileType);
result.then(response => {
  fs.createWriteStream('file_response.pdf').write(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const templateApi = new DropboxSign.TemplateApi();

// Configure HTTP basic authorization: api_key
templateApi.username = "YOUR_API_KEY";

// or, configure Bearer (JWT) authorization: oauth2
// templateApi.accessToken = "YOUR_ACCESS_TOKEN";

const templateId = "5de8179668f2033afac48da1868d0093bf133266";

const result = templateApi.templateFilesAsDataUri(templateId);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const templateApi = new DropboxSign.TemplateApi();

// Configure HTTP basic authorization: api_key
templateApi.username = "YOUR_API_KEY";

// or, configure Bearer (JWT) authorization: oauth2
// templateApi.accessToken = "YOUR_ACCESS_TOKEN";

const templateId = "5de8179668f2033afac48da1868d0093bf133266";

const result = templateApi.templateFilesAsFileUrl(templateId);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Endpoint Mapping

This section shows you how endpoints in the legacy SDK map to the new SDK. It doesn't cover all endpoints, but gives you an idea of mapping implementations between the two SDKs. Please reach out if you think we're missing an important example.

Get Account

Legacy SDK - Get AccountNew SDK - Get Account
Copy
Copied
const hellosign = require('hellosign-sdk')({ key: process.env.HelloSign_API_KEY });

hellosign.account.get().then((res) => {
    console.log(res)
}).catch((err) => {
    console.log(err)
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const accountApi = new DropboxSign.AccountApi();

accountApi.username = "YOUR_API_KEY";

const result = accountApi.accountGet();
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Get Signature Request

Legacy SDK - Get Signature RequestNew SDK - Get Signature Request
Copy
Copied
const hellosign = require('hellosign-sdk')({ key: 'HelloSign_API_KEY' });

hellosign.signatureRequest.get(SIGNATURE_REQUEST_ID).then((res) => {
    console.log(res)
}).catch((err) => {
    console.log(err)
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureApi = new DropboxSign.SignatureRequestApi();

signatureApi.username = 'YOUR_API_KEY';

const signatureRequestId = "SIGNATURE_REQUEST_ID";

const result = signatureApi.signatureRequestGet(signatureRequestId);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Send Signature Request

Legacy SDK - Send Signature RequestNew SDK - Send Signature Request
Copy
Copied
const hellosign = require('hellosign-sdk')({ key: 'HelloSign_API_KEY' });

var signers = [
  {
    email_address : 'jack@example.com',
    name : 'Jack',
    order : 0,
  },
  {
    email_address : 'jill@example.com',
    name : 'Jill',
    order : 1,
  }
]

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,
  cc_email_addresses : ['lawyer@example.com', 'lawyer2@example.com'],
  files : ['./Demo-Mutual-Non-Disclosure-Agreement.pdf'],
  metadata : {
    clientId : '1234',
    custom_text : 'NDA #9'
  }
};

hellosign.signatureRequest.send(options)
.then(function(res){
  console.log(res.signature_request);
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";
const fs = require('fs');

const signatureApi = new DropboxSign.SignatureRequestApi();

signatureApi.username = 'YOUR_API_KEY';

const myFile = fs.createReadStream('./Demo-Mutual-Non-Disclosure-Agreement.pdf');

const signer1 = {
  emailAddress: "jack@example.com",
  name: "Jack",
  order: 0,
};

const signer2 = {
  emailAddress: "jill@example.com",
  name: "Jill",
  order: 1,
};

const data = {
  testMode: true,
  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: [ signer1, signer2 ],
  ccEmailAddresses: [
    "austin.hs.demo@gmail.com",
    "dbxsign.test@gmail.com",
  ],
  files: [myFile],
  metadata: {
    "custom_id": 1234,
    "custom_text": "NDA #9",
  }
};

const result = signatureApi.signatureRequestSend(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Create Embedded with Template

Legacy SDK - Create Embedded with TemplateNew SDK - Create Embedded with Template
Copy
Copied
const hellosign = require('hellosign-sdk')({ key: 'HelloSign_API_KEY' });

var options = {
  test_mode : 1,
  clientId : 'CLIENT_ID',
  template_id : 'TEMPLATE_ID',
  subject : 'Purchase Order',
  message : 'Glad we could come to an agreement.',
  signers : [
    {
      role : 'Client',
      email_address : 'george@example.com',
      name : 'George',
    }
  ]
};

hellosign.signatureRequest.createEmbeddedWithTemplate(options);
.then(function(res){
  console.log(res.signature_request);
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const signatureApi = new DropboxSign.SignatureRequestApi();

signatureApi.username = 'YOUR_API_KEY';

const signer1 = {
  role: "Client",
  emailAddress: "george@example.com",
  name: "George",
};

const data = {
  testMode: true,
  clientId: "CLIENT_ID",
  templateIds: ["TEMPLATE_ID"],
  subject: "Purchase Order",
  message: "Glad we could come to an agreement.",
  signers: [ signer1 ]
};

const result = signatureApi.signatureRequestCreateEmbeddedWithTemplate(data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Update API App

Legacy SDK - Update API AppNew SDK - Update API App
Copy
Copied
const opts = {
  name: 'My Cool App',
  white_labeling_options: '{"primary_button_color":"#ff0000","primary_button_text_color":"#000000"}'
};

hellosign.apiApp.update('CLIENT_ID', opts).then((res) => {
  console.log(res)
}).catch((err) => {
  console.log(err)
});
Copy
Copied
import * as DropboxSign from "@dropbox/sign";

const apiAppApi = new DropboxSign.ApiAppApi();

apiAppApi.username = "YOUR_API_KEY";

const whiteLabelingOptions = {
  primaryButtonColor: "#00b3e6",
  primaryButtonTextColor: "#ffffff",
};
const data = {
  whiteLabelingOptions,
};
const clientId = "CLIENT_ID";

const result = apiAppApi.apiAppUpdate(clientId, data);
result.then(response => {
  console.log(response.body);
}).catch(error => {
  console.log("Exception when calling Dropbox Sign API:");
  console.log(error.body);
});

Supporting Legacy SDKs

Following the official release of the new SDK version, we'll be preparing to deprecate all legacy versions of the Node SDK for one year after launch. That means, once fully launched, we'll only support critical vulnerabilities and bug fixes for legacy SDK versions 2.1.0 for 12 months. After that, legacy versions are considered officially deprecated and are no longer supported. You can find more information in our SDK Versioning Policy.

We encourage you to start migrating (or planning to migrate) to the new SDK as soon as possible. Please don't hesitate to reach out if you have questions or need assistance.


Feedback and Assistance

We know that dealing with "breaking" changes is inconvenient for those of you currently using the legacy SDK, but believe the new SDK offers a better experience while providing access to more features. If you need help or get stuck, please reach out to API support: Submit a Ticket

We warmly welcome your feedback, feature requests, and bug reports in our OpenAPI repo. All of the engineering work on the Node SDK happens in the Node folder of the repo.