NAV navbar api docs
home legalesign api logo
shell php python ruby

API Reference


API examples

CURL is used throughout this reference, PHP, python and ruby examples are given in Quickstart.


Open-source libraries by developers who have integrated with Legalesign. With thanks to: Marcus Sanatan, Tyler Menezes:

    PHP - https://legalesign.com/blog/esignature-php-library/
    NODE.js - https://legalesign.com/blog/esignature-node-api/


Some comments from previous API developers -- 

"Using the Legalesign API is a breeze, sending and processing e-signed documents couldn't be easier"

-- James, Director of Information Systems @ Ready Project, www.readyproject.com


"I am definitely planning on using the Legalesign API again soon. I appreciated the support and attention to security."

-- Arthur King, Head of IT, N4Gtv.com




Legalesign.com is an electronic signature software-as-a-service. This is the reference for its API. You can partially or fully integrate with Legalesign to create your own e-signature system.

API integration is cost-effective against developing bespoke solutions and is recommended over in-house systems to mitigate accusations of document tampering. In additional upgrades, patching, support and monitoring come as standard.

Legalesign is designed with API useage in mind:

Sign up for a trial to get your API keys and so the code in this reference will work for you.

For pricing information and technical assistance contact us.

If you are seeking to integrate Legalesign with another app (basecamp, freeagent, gmail etc) first check out Zapier.com. Zapier enables you to integrate apps without coding. Use this link to join Legalesign on Zapier: click here to use Legalesign on Zapier

Quickstart

Send out a document to be signed, get notified when the document is fully executed and pull down the final pdf.

Send a HTML document to be signed

    curl --dump-header -
    -H "Authorization: [auth_code]"
    -H "Content-Type: application/json"
    -X POST --data '{
    "group": "/api/v1/group/your-group/",
    "name": "Name of doc",
    "text": "<h1>Non disclosure agreement</h1><p>terms as follows.. <span class='field' data-optional='false' data-name='Please add your ...' data-idx='0' data-signee='1' data-type='signature' data-options=''> ....... </span></p>",
    "signers":
        [{"firstname": "Joe",
        "lastname": "Bloggs",
        "email": "sandbox@email.com",
        "order": 0
        }],
    "do_email": "true"
    }'
    https://api.legalesign.com/api/v1/document/
<?php
    //Accessing Legalesign API using the Guzzle PHP REST API client
    //http://guzzlephp.org/, follow install instructions at: https://github.com/guzzle/guzzle

    require_once 'vendor/autoload.php';
    use GuzzleHttp\Client;


    $auth_header = 'ApiKey [username]:[key]';
    $headers = ['Authorization' => auth_header, 'Content-Type' => 'application/json'];

    $client = new Client();

    //EXAMPLE OF GET - GET THIS USERS GROUPS

    $groups_endpoint = 'https://api.legalesign.com/api/v1/group/';

    $response = $client->get($groups_endpoint, ['headers' => $headers]);

    echo 'status code: ';
    echo $response->getStatusCode();

    $data = json_decode($response->getBody());
    echo 'json data: ';
    print_r($data->objects);



    //EXAMPLE OF POST - SEND A DOCUMENT

    //array of signers, note arrays within array
    $signers_post = array(
                          array(
                                'firstname'=>'Joe',
                                'lastname'=>'Bloggs',
                                'email'=>'sandbox@email.com',
                                'order'=>0,
                               )
    );
    //doc variables
    $doc_post = array(
                      'group'=>'/api/v1/group/your-group/',
                      'name'=>'Name of doc',
                      'text'=>'<h1>Non disclosure agreement</h1><p>terms as follows.. <span class='field' data-optional='false' data-name='Please add your ...' data-idx='0' data-signee='1' data-type='signature' data-options=''> ....... </span></p>',
                      'signers'=>$signers_post,
                      'do_email'=>True,
                      );


    //encode in json and post
    $json_data = json_encode($doc_post);

    $post_document_endpoint = 'https://api.legalesign.com/api/v1/document/';

    echo 'sending...';
    $resp = $client->post($post_document_endpoint, ['headers' => $headers, 'body' => $json_data]);

    echo 'status code:';
    echo $resp->getStatusCode();   //201 created response expected

    //new docs resource_uri is contained in 'Location' header
    $doc_resource_uri = $response->getHeader('Location');
    echo $doc_resource_uri;
    //https://api.legalesign.com/api/v1/status/[doc-id]/


    //Send a PDF doc that has been set up on Legalesign
    //with the text for 'sender fields' (i.e. custom text for doc)

    //for the sender fields, create array using the field labels for keys
    $sender_text= array(
        'label 1' => 'first value',
        'label 2'=>'another value',
    );

    //use 'pdftext' to send the sender field information

    $doc_post = array(
                      'group'=>'/api/v1/group/your-group/',
                      'name'=>'Name of doc',
                      'templatepdf'=>'/api/v1/templatepdf/[pdf-id]/',
                      'signers'=>$signers_post,
                      'do_email'=>True,
                      'pdftext'=>$sender_text,
                      );

    $json_data = json_encode($doc_post);

    $resp = $client->post($post_document_endpoint, ['headers' => $headers, 'body' => $json_data]);
    $resp->getStatusCode(); //201 created response expected

    ?>
    import slumber
    from requests import session

    username = '[username]'
    api_key = '[key]'
    url = 'https://api.legalesign.com/api/v1/'

    sess = session()
    sess.headers.update({'Authorization': 'ApiKey %s:%s' % (username, api_key) })
    api = slumber.API(url, session=sess)

    resp = api.status.get()
    print resp

    //signers info - note signer dictionary is within a list

    signers = [
        {
            'firstname': 'Joe',
            'lastname': 'Bloggs',
            'email': 'sandbox@email.com',
            'order': 0,
        }
    ]

    //Send HTML directly

    data_post = {
        'name': 'first test doc',
        'group': '/api/v1/group/your-group/',
        'do_email': True,
        'signers': signers,    
        'text': '<h1>Non disclosure agreement</h1><p>terms as follows.. <span class='field' data-optional='false' data-name='Please add your ...' data-idx='0' data-signee='1' data-type='signature' data-options=''> ....... </span></p>',
    }

    resp = api.document.post(data_post)
    print resp
    'OK'


    //Send a PDF doc that has been set up on Legalesign
    //with the text for sections that need to be completed by sender

    //for sender text, create array with the text section labels for keys
    sender_text = {
        'label 1': 'First value',
        'label 2': 'Second value'
    }

    data_post = {
        'name': 'first test doc',
        'group': '/api/v1/group'/api/v1/group/your-group/',
        'do_email': True,
        'signers': signers,
        'templatepdf': '/api/v1/templatepdf/[id]',
        'pdftext': sender_text,
        'signature_type': 4
    }

    resp = api.document.post(data_post)
    print resp
    'OK'
    require 'httparty'

    username = '[username]'
    key = '[key]'
    url = 'https://api.legalesign.com/api/v1/document/'

    header = {'Authorization' => 'ApiKey '+username+':'+key, 'Content-Type' => 'application/json'}

    signers_data = [
        { 'firstname' => 'Joe', 'lastname' => 'Bloggs', 'email' => '', 'order' => 0}
    ]

    //SendHTML directly

    post_data  = {
        'name' => 'Test doc ruby',
        'group' => '/api/v1/group/<your-group>/',
        'text' => '<h1>Non disclosure agreement</h1><p>terms as follows.. <span class='field' data-optional='false' data-name='Please add your ...' data-idx='0' data-signee='1' data-type='signature' data-options=''> ....... </span></p>',
        'do_email'=> true,
        'signers'=> signers_data,
    }

    resp = HTTParty.post('https://api.legalesign.com/api/v1/document/', :body=>post_data.to_json, :headers=>auth_headers)
    resp.parsed_response
    "OK"


    //Send a PDF doc that has been set up on Legalesign
    //with the text for sections that need to be completed by sender

    //for sender text, create array with the text section labels for keys
    sender_text = {
        'label 1'=> 'First value',
        'label 2'=> 'Second value'
    }

    data_post = {
        'name' => 'first test doc',
        'group' => '/api/v1/group/your-group/',
        'do_email' => True,
        'signers' => signers,
        'templatepdf' => '/api/v1/templatepdf/[pdf-id]',
        'pdftext' => sender_text
    }

    resp = HTTParty.post('https://api.legalesign.com/api/v1/document/', :body=>post_data.to_json, :headers=>auth_headers)
    resp.parsed_response
    "OK"

API key & sandbox recipients

First go to your settings page create an API key and add up to 5 emails where you will send your test documents.

Send a doc to be signed

In this example we will send HTML, but you can upload a PDF/Word or refer to a template you already prepared.

While HTML appears to be more primitive than a PDF it is most popular since it gives you a fast and full freedom in the construction of each document you send.

Study the example in the right column. ApiKey credentials go in an Authorization header, the content type header is used to specify for the data being POSTed, and a JSON dictionary used for data and it is pushed the /document/ endpoint.

A successful response will deliver back a 201 status, and the new document status resource_uri is returned in the Location header. It will look like: https://api.legalesign.com/api/v1/status/[doc-id]/.

Get the doc status

After sending, use the status endpoint (from the Location header) to poll the document status. For production, do not poll, Event Notifications will tell you about changes when they happen.

Poll

Get the document status - here is an example using the status endpoint (you will get the real full endpoint out of the Location header in the response from the POST you made to create/send out a document.

curl --dump-header - -H "Authorization: [auth_code]" -H "Content-Type: application/json"
    -X GET https://api.legalesign.com/api/v1/status/[doc-id]/

See the example code for a poll request to the status endpoint (i.e. the Location header that is returned when the document is successfully created)

Concise response from /status/ endpoint

    {
    "archived": false, 
    "resource_uri": "/api/v1/status/[doc-id]/", 
    "status": 30,
    "download_final: true,
    }

The status endpoint delivers a concise response with key information. See an example response on the right: status '30’ that indicates the document has been signed - see Document Status Codes, and 'download_final’ confirms that the final document has been created and is available for download.

To retrieve all the document attributes use the /document/[doc-id]/ endpoint.

Event notification upon signing

Rather than make repeated queries, define your own URL endpoint to receive notifications about activity on Legalesign. There are two notification systems: i) be notified when a document is signed, or ii) get all changes of every kind (document visited, fields completed etc. for both document and signer) every 6 minutes.

You can add your notification programmatically, or email it to us to set up - for more information go to Event notifications.

JSON POSTED to you by event notification

    {'data': [u'[{"timestamp": "2016-12-06T17:49:46",
   "name": "status", "value": "30",
    "resource_uri": "/api/v1/document/[doc-id]/"}]'],
    u'signed': [u'long_string_of_letters_and_numbers']}

The example shows a typical package from the notification option to receive all information every 6 minutes. See the example to the right - 'JSON POSTED to you by event notification’. Looking into the data, the document at /api/v1/document/[doc-id]/ status has been changed to 30, i.e. signed.

(For document status codes see: Document Status Codes )

Notifications include both signer and document changes (thus the final signing on a doc will include at least two data dictionaries for that doc - one for the signer and one for the document). If the notification refers to a signer then 'resource_uri’, will point to a signer resource, e.g. ’/api/v1/signer/[signer-id]/’ and if it refers to a document the resource_uri will refer to the document, e.g. ’/api/v1/document/[doc-id]/’.

The 'signed’ part of the data is a base64 encoded signed string you can use along with the Legalesign x509 certficate to verify we really sent the data, should you wish to double check.

For more information on callack go to Event notifications.

Get the final PDF

Download the signed document

    curl --dump-header -o download.pdf - -H "Authorization: [auth_code]" 
    -X GET https://api.legalesign.com/api/v1/pdf/[doc-id]/

Once a document is signed make a GET request to the pdf endpoint to pull down the signed pdf.

If you wish to verify the download, the SHA-256 hash value for the signed pdf is available from the document endpoint (i.e https://api.legalesign.com/api/v1/document/[doc-id]/)

There can be a lag between signing and final PDF creation. To make sure the download is available use either (1 ) 'document_final’ boolean provided in the /document/ or /status/ endpoints or (2) code '100’ in the callback system.

Finishing up

Archive document, if you set auto_archive to false when you sent the document

    curl --dump-header - -H "Authorization: [auth_code]" -H "Content-Type: application/json"
     -X PATCH --data '{ "archived": true }'
     https://api.legalesign.com/api/v1/archived/[doc-id]/

Since auto_archive is set to true by default when we originally sent the POST request earlier, the document will get sent to the archive automatically once it is signed. But otherwise you will need to archive it.

Archiving prevents the web interface from building up clutter if it is rarely being used.

But if you set auto_archive to false, then you can finish up by archiving the document, perhaps after a given time lapse.

Background

Authentication

To get a key go to your settings page where you can generate API access details. Upon generation you will be provided with the auth code for making API requests.

Auth in Header

Authorization: ApiKey [username]:[key]

Auth in Query Paramaters

https://api.legalesign.com//api/v1/[an-endpoint]/?username=[username]&api_key=[key]

Authorization

API Keys are provided on a per-user basis. API access will have the same level of authorization as the user in the web interface. The user will be able to access the templates, documents and members of all the groups to which the API user belongs.

We recommend you create a non-specific ‘master’ user for your firm and then add individual member accounts to each group. Use the 'master’ for API access, to sign up to service plans and create groups. This way you do not tie control of your groups to an individual, you ensure that you do not buy multiple plans for different sets of groups.

Sandbox mode

Sandbox is a free version of Legalesign to set up and test your integration.

You can send documents to up to 5 different emails. Add those emails on your settings page, at the same place you find your API Key.

Once you are ready for production let us know. Once in production you will be able to send documents to any email.

If you try and send a document to someone not on your testing email list you will receive a 401 Not Authorized response.

API URL

Your root url is: https://api.legalesign.com/

Format

Send your data in JSON or XML and specify the format in your querystring ("format=[json,xml]") or the Content-Type header (application/json, application/xml).

Accepts header in curl

curl -H "Accept: application/xml" -X GET https://api.legalesign.com/api/v1/

Content-Type for sending data to the server

curl -H "Content-Type: application/json" -X POST -- data {...} https://api.legalesign.com/api/v1/

A querystring

/api/resource/url/?format=json

Throttling

Once you start using the API in production you will have agreed a monthly usage limit with us. You will also find hourly throttle limits on your settings page

All throttle limits are 'soft’, that is, you can exceed them without loss of service. We will get in touch if something looks amiss.

    curl -H "Authorization: [auth_code]"
    https://api.legalesign.com/api/v1/throttle/

Will respond::

     {"limit": 100, "requests_in_last_hour": 22}

The hourly throttle is largely for our management purposes. Some spikes will cause us to contact you. But if you exceed the defined hourly limit it will rise automatically so you do not lose service.

If we do apply a throttle the throttled request will return HTTP code 429.

Event notifications are not included in throttle limits.

You can check the status of your hourly throttle rate by calling the /throttle/ endpoint. It will return your limit and requests in the last hour.

Methods

Each resource should list the methods available.

POST will return 'Location’ header with the detail endpoint for the new object

Time format

All times are in UTC. Most objects have 'created’ and 'modified’ attributes, a datetime is formatted as::

YYYY-mm-ddTH:M:S

Response codes

If a request fails check the BODY of the response for any error messaging.

Why a user attribute?

POST requests require a user attribute. You can send on behalf of other users in the group.

Common issues/Debugging

  1. Make sure all endpoints and resource_uri end with a slash - '/'
  2. Document create - make sure your signer hash dictionary is within a list
  3. Make sure you include the Content-Type header

Avoid frustration and contact us (with the problematic code snippet if possible)

Documents

Documents are objects that have been sent out to be signed.

document/

Sample GET response in JSON:

    {
    "meta": {
    "limit": 20, 
    "next": "/api/v1/document/?username=[username]&api_key=[key]&limit=20&offset=20&format=json", 
    "offset": 0, 
    "previous": null, 
    "total_count": 49
    }, 
    "objects": [
    {
      "archived": false, 
      "created": "2016-12-06T17:49:46", 
      "group": "/api/v1/group/your-group/, 
      "modified": "2016-12-06T17:49:46", 
      "name": "Doc 1",
      "download_final": true,   //bool indicates final PDF is available for download
      "resource_uri": "/api/v1/document/[doc-id]/",
      "signers": [
        [
            "api/v1/signer/[signer-id]", 
            "firstname", 
            "lastname", 
            "[email]",
            "behalf of",
            true, //whether this signer has fields to complete
            40,   //signer status 
            0     //signer order (zero-indexed)
        ]
      ], 
      "status": 30,  #document status
      "user": "/api/v1/user/[user-id]/", 
      "uuid": "[user-id]"
    }, 
    {
      "archived": false, 
      "created": "2016-12-06T17:49:46", 
      "group": "/api/v1/group/your-group/", 
      "modified": "2016-12-06T17:49:46", 
      "name": "Doc 2",
      "download_final": false,
      "resource_uri": "/api/v1/document/[doc-id]/",
      "signers": [
        [
            "api/v1/signer/2c7f7ac4-7226-4608-b2aa-765fca2473f5",
            "firstname", 
            "lastname", 
            "[email]", 
            "behalf of",
            false, //whether this signer has fields to complete
            10,   //signer status 
            0     //signer order (zero-indexed)
        ]
      ], 
      "status": 10, #document status
      "user": "/api/v1/username/[sample]/", 
      "uuid": "[username]"
    },
    ...

Return documents that have not been archived or send a document to be signed.

Allowed methods: GET, POST

A GET request automatically filters archived documents. To get all documents (i.e. archived and unarchived) add ?archived=all&... to the querystring or specify ?archived=true for the archive only. The list can also be filtered by signer email ?email=sandbox@email.com&..., or lastname ?lastname=Bloggs&..., group url name ?group=your-group&... or group resource_uri ?group=/api/v1/group/your-group/&... and by status ?status=30&... (show only signed docs).

Document status codes are as follows:

Status Explanation
10 Sent
20 Fields completed
30 Signed
40 Removed (before signing)
50 Rejected

Signer status codes are as follows:

Status Explanation
5 Scheduled/Unsent
10 Sent
15 Email opened
20 Visited
30 Fields completed
40 Signed
50 Downloaded
60 Rejected

A POST request will send out a new document to signers.

Example of a POST request in curl::

    curl --dump-header - -H "Authorization: [auth_code]" -H "Content-Type: application/json"
    -X POST --data '{ "group": "/api/v1/group/your-group/", 
    "name": "Name of doc", "template": "/api/v1/template/[template-id]/",
    "signers": [{"firstname": "Joe", "lastname": "Bloggs",
    "email": "sandbox@email.com", "order": 0 }],
    "do_email": true}' https://api.legalesign.com/api/v1/document/

In the example POST, an existing text template is being called, there is 1 signer. Legalesign will send out the notification emails to signers.

Example of the response from a successful POST. The document’s status resource_uri is in the Location header::

    HTTP/1.0 201 CREATED
    Expires: -1
    Vary: Accept
    Location: https://api.legalesign.com/api/v1/status/[doc-id]/
    Pragma: no-cache
    Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Content-Type: application/json
    Connection: close
    Server: xxx
    Date: xxx
    "OK"

Example of a response from a failed POST, where name is omitted

    HTTP/1.0 400 BAD REQUEST
    Expires: -1
    Content-Type: application/json
    Pragma: no-cache
    Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Connection: close
    Server:xxx
    Date: xxx
    {
        "document": {
          "name": [
            "This field is required."
          ]
        }
      }

POST attributes:

Attribute Type Required Details
group resource_uri Y The group you’re using to send the document
name string Y Name of document, max length 60
signers list Y See below. A list of signer dictionary objects
template* resource_uri N* Text/HTML document to send (already saved to site).
text* string N* Full HTML of doc.
templatepdf* resource_uri N* PDF document to send (already saved to site).
append_pdf bool N Default=false. Append Legalesign validation info to final PDF. If not included uses the group default.
auto_archive bool N Default=true. Send to archive a few hours after signing*. Keeps web interface clutter free.
do_email bool N Default=false. If true will use Legalesign email to send notification emails
cc_emails string N Comma delimited list of email addresses that are cc’d into the email that confirms a signing/rejection.
footer string N The footer for the final pdf. Use keyword ‘default’ to use group’s default footer
footer_height integer N Pixel height of PDF footer, if used. 1px = 0.025cm
header string N The header for the final pdf. Use keyword 'default’ to use group’s default header
header_height integer N Pixel height of PDF header if used. 1px = 0.025cm
pdftext dict N Sender text for pdf (if used), use element label for keys
return_signer_links bool N Default=false. Return document links for signers in the response BODY. Not recommended.
signature_placement integer N Default=1. 1=Foot of each page, 2=End of document
signature_type integer N Default=1. 4 RECOMMENDED. 4=PDF Certification plus Legalesign Validation, 1=Legalesign validation only
signers_in_order bool N Default=false. Notify signers in their order sequence. If false all are notified simulataneously
user resource_uri N Will assign document to user with API key if omitted
pdf_password string N Assign a password to the final PDF, requires pdf_password_type set at group level, or using attribute pdf_password_type
pdf_password_type integer N If using pdf_password. Not needed if set at group level. 1 = Password is kept by us. 2 = Password is deleted after shown to first signer.
Important notes

Signer attributes. A signer should be a dictionary object with the following attributes

Attribute Type Notes
firstname string required, max length 60. The following characters are disallowed: ’“\,;:<>=\
lastname string required, max length 60. The following characters are disallowed: ’”\,;:<>=\
email string required, max length 75.
behalfof string optional, max length 120
order integer required, must be zero-indexed and sequential
message* string optional, use 'default’ to use group’s default message
subject string optional, email subject line. Will use team’s default if blank, max length 150

If successful the response from your POST request will be a 201. It will contain the new resource_uri in the 'Location’ header and , if you set return_signer_links to true, the URL links for each signer in the BODY. If you are sending out notification emails yourself you can use these signer links in your emails.

If the request fails you will receive a 400 and the BODY will contain an error report.

Iframe - embed in your own site

Important - let us know if you wish to use iframes so they are enabled within your account settings.

To use an iframe in your own site get the URL by using the 'return_signer_links’ attribute, then extract the iframe URL from the BODY of the response.

When you put the URL link in your iframe you can add two GET queries - hidetext=1 and/or hidenav=1. They will condense the size of the page and hide the navigation +/or the extra text on the signing page.

Browser-side, to tell your parent frame when a document is complete, you will immediately receive one of three possible javascript messages using postMessage: 'waiting’, 'signed’, 'rejected’. If the document has been signed then you will also get the message 'download’ when the document download button is clicked.

You will get a 'waiting’ message if you have more than 1 signer and the document still needs other people to sign it.

For more information about postMessage see https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage.

Use event notifications to get notified server-side of signer actions.

document/[doc-id]/

Return a specific document details (extended)

Available methods: GET, DELETE

Example of a GET in JSON

 {
  "archived": false, 
  "created": "2016-12-06T17:49:46", 
  "footer": "",
  "footer_height": null, 
  "group": "/api/v1/group/your-group/", 
  "has_fields": true,
  "download_final": false,  //bool indicates final pdf is available to download
  "hash_value": null,  //the hash of the final pdf (when signed)
  "header": "", 
  "header_height": null, 
  "modified": "2016-12-06T17:49:46", 
  "name": "opt1", 
  "resource_uri": "/api/v1/document/[doc-id]/", 
  "sign_time": null, 
  "signature_placement": 2, //1 = place on each page, 2= place at end of doc
  "signature_type": 1, //1 = basic signature, 2 = advanced esignature
  "signers": [
    [
        "api/v1/signer/[signer-id]/,
        "Joe", 
        "Bloggs", 
        "sandbox@email.com",
        "behalf of",
        true, //whether this signer has fields to complete
        30,   //signer status 
        0     //signer order (zero-indexed)
    ]
  ], 
  "status": 20, 
  "text": "<html>\n <head>\n </head>\n <body>\n  <p>\n   <span class=\"field\" data-auto=\"\" data-idx=\"0\" data-name=\"Write your name\" data-optional=\"false\" data-options=\"\" data-signee=\"1\" data-state=\"1\" data-type=\"text\">\n    d\n   </span>\n</body>\n</html>", 
  "user": "/api/v1/username/[sample]/", 
  "uuid": "[username]"
  }

Example of a DELETE in curl

    curl --dump-header - -H "Authorization: [auth_code]" -X DELETE
    https://api.legalesign.com/api/v1/document/[doc-id]/

Some attributes explained:

Attribute Type Explanation
signature placement integer 1=place signature on each page, 2=place at end of doc
signature_type integer 1=basic signature, 4=certified pdf
has_fields bool Whether or not the document has fields to complete
hash_value string The hash value of the final pdf

Important note about DELETE for a document:

DELETE does not remove the document permanently it marks the document status as 'removed’ and archives the document.

In the web interface deletion will trigger emails to the signers to tell them the document is void, these email are not triggered through this API call. You will need to send these emails through your own system.

Example in curl

     curl --dump-header - -H "Authorization: [auth_code]" -H "Content-Type: application/json"
     -X PATCH --data '{ "archived": true }'
     https://api.legalesign.com/api/v1/archived/[doc-id]/

If you sent a document and turned off auto_archive you can archive (or unarchive it) via the API by sending a PATCH request with data archived=True/False.

This will only archive or unarchive the doc if it is signed. To remove and void a document before it is signed use the DELETE method at the document/[doc-id]/ endpoint.

Allowed methods: GET, PATCH

If the document is not signed you will get a 400 error code and the following error message::

    {
      "archived": {
        "status": [
          "Document cannot be archived unless it is signed"
        ]
    }

document/preview/

Returns a redirect response (302) with link in the Location header to a one-use temporary URL you can redirect to, to see a preview of the signing page. Follow the redirect immediately since it expires after a few seconds.

Allowed methods: POST

Attribute Type Required Notes
text string Y
title string Y
group resource_uri Y
signee_count integer N defaults to 2

status/

Return document status, whether archived and document group. Status returns a shortened version of the /document/ endpoint.

Allowed methods: GET

Filters for unarchived documents by default. Add ?filter=false or ?filter=all for archived or all documents. Filter by group by adding a group parameter to the querystring. Use either the group url name or the group resource_uri, e.g. ?group=your-group or ?group=/api/v1/group/your-group/

For status codes see: Document Status Codes

Example GET response in JSON

    {
      "meta": {
        "limit": 20, 
        "next": "/api/v1/status/?username=[username]&api_key=[key]&limit=20&offset=20&format=json", 
        "offset": 0, 
        "previous": null, 
        "total_count": 64
      }, 
      "objects": [
        {
          "archived": false, 
          "resource_uri": "/api/v1/status/[doc-id]/", 
          "status": 30,
          "download_final": true,
        },
        ...

status/[doc-id]/

Return single document status

Allowed methods: GET

Example GET response in JSON

    {
    "archived": false, 
    "resource_uri": "/api/v1/status/[doc-id]/", 
    "status": 30,
    "download_final": true,
    }

For status codes see: Document Status Codes

signer/[signer-id]/

Return status and other details of an individual document signer. Each signer has an associated user object (that contains name and email) and a document object. 'has_fields’ indicates whether the signer has fields to complete.

Allowed methods: GET

Example of a GET response in JSON

    {
    "document": "/api/v1/document/[doc-id]/", 
    "email": "sandbox@email.com", 
    "first_name": "Joe", 
    "last_name": "Bloggs", 
    "has_fields": true, 
    "order": 0, 
    "resource_uri": "/api/v1/signer/[signer-id]/", 
    "status": 40
    }

signer/[signer-id]/send-reminder/

Send a reminder email to a signer. Takes optional data 'text’, a text string with a message for the signer. HTML will be stripped. The reminder email includes a new link to the document for the signer.

Returns http response 200 'OK’.

Allowed methods:POST

signer/[signer-id]/reset/

If a document has been forwarded use this endpoint to return the document to earlier signers.

Will return an error if the document has been signed, if the document’s current signer email is the same as the one sent, or if the email is not found to be an earlier signer. Explanatory text for errors will be found the in the BODY of the response.

Allowed methods: POST

Attribute Type Required Notes
email string Y email of earlier signer
notify boolean N Default false. Email the current signer to say the document has been called back

Returns http response 200 'OK’.

Allowed methods:POST

signer/[signer-id]/new-link/

Returns the document link for the signer in the response 'Location’ header. Useful if you want to send your own reminder emails. Link is specific to this signer.

If the signer does not have an account with Legalesign this will be a 1-use link to the document. For existing users it will be a link direct to the document if the user is logged in or via the login page if not.

Returns http response 200.

Allowed methods:GET

signer/[signer-id]/fields1/

Allowed methods: GET

Will return a json list of hash dictionaries describing the form fields to be completed by the signer

Attribute Type Description
label string The label of the field, if given
value string Value of field, checkboxes will return html
fieldorder integer If ordering is used, it is specified here (PDF only)
state boolean If true the field has been saved by the signer

pdf/[doc-id]/

Returns the raw PDF data for either the draft PDF if unsigned, or the final PDF if signed.

Allowed methods: GET

Example of a GET request in curl

    curl --dump-header - -H "Authorization: [auth_code]
" 
    -X GET -o finaldoc.pdf
    https://api.legalesign.com/api/v1/pdf/[doc-id]/

Once signed the /document/[doc-id]/ endpoint will include the SHA-256 hash value (attribute 'hash_value’) for the signed pdf. You can use the hash value to ensure the downloaded document is not corrupted during delivery.

If you request an old PDF it may have gone into deep storage and not be immediately available. In this case you will received a 202 HTTP code. A storage request will have been created and if you try again after 5 hours it wil be available. If you use the callbacks it will also include an entry when the document is available: the resource_uri will be the relevant document, the name will be 'storage_retrieval’ and the value will be 'completed’.

pdf/preview/

Returns raw data of PDF preview. Useful when preparing text templates, documents, headers or footers.

Allowed methods: POST

Attribute Type Required Description
text string Y html of the document
signee_count integer Y number of signers
signature_type integer Y 1=basic signature, 4 certified document
is_signature_per_page integer Y 1=signatures on each page, 2=signatures at end of doc
group resource_uri Y the relevant group (for the default header/footer if used)
title string N document title
header string N html for header at top of each page
header_height integer N required if using header, pixel height of header, 1px=0.025cm
footer_height integer N required if using footer, pixel height of footer, 1px=0.025cm
pdfheader bool N set to 'true’ to use group default header and footer

Event Notifications

Get notified when something happens on Legalesign. These do not affect your API throttle limit.

Tell us a URL endpoint and we will POST you changes in your groups.

There are two callback options, you can use either, or both.

  1. Receive everything that has happened in the last 6 minutes, every 6 minutes - signer status changes and document status changes
  2. Receive notification a document has been signed in real-time.

The second option is easier to implement. If you only need to know when something has been signed use the second option. If you need more information - when a signer opens an email, or views a document - use the first option.

In either case, tell us your URL endpoint and whether you want option 1 or 2. If you prefer to subscribe/unsubscribe programmatically you can use the following endpoints:

Subscribe

Using your regular API authentication, POST to https://api.legalesign.com/api/subscribe/ , with attributes ‘url’ and 'notify’. The 'url’ attribute should contain your callback url, and the notify value should either be 'all’ (for option 1) or 'signed’ (for option 2).

Unsubscribe

Using your regular API authentication, POST to https://api.legalesign.com/api/unsubscribe/ with the 'url’ attribute and relevant url to remove.

Warning - if your callback URL fails to respond they will be suspended, so please contact us when you’ve tested and confirmed your URL is accessible.

Option 1. Everything every 6 minutes.

Example of the JSON that will be POSTED to you::

    {
    u'data':
        [
          u'[
                {
                "timestamp": "2016-12-06T17:49:46",
                "name": "status",
                "value": "40",
                "resource_uri": "/api/v1/signer/[signer-id]/"
                },
                {
                "timestamp": "2016-12-06T17:49:46",
                "name": "status", "value": "30",
                "resource_uri": "/api/v1/document/[doc-id]/"
                }
            ]'
        ],
    u'signed':
        [u'long_string_of_numbers_and_digits']
    }

This tells you that signer "/api/v1/signer/[signer-id]/" changed to status 40 (signed) at 2016-12-06T17:49:46, and that document '/api/v1/document/[doc-id]/' was fully signed (status 30) at 2016-12-06T17:49:46. (A signed document has status 30, while a signed signer has status 40.) The dictionary will contain each status change in order they occured with the timestamp, so it is likely to contain multiple status changes for a single signer.

Data is POSTED in two sections 'data’ and 'signed’. The data section is a JSON object that is a list of dictionaries of the changes. The dictionaries are a record of each change to document and siger status in the order they occured. The second section is a signed string (base64 encoded) you can use to verify the data is genuine should you wish.

The data contains a list of dictionaries that contains the notification information.

Attributes Explantion
timestamp ISO format of when the change occured
resource_uri The object the notification relates to.
name What the message relates to
value The value the message relates to.

'status’ - Document and Signer Status

The majority of callback will have the name 'status’ and these refer to status changes for signers and documents. The codes for those status changes will be in value.

For document status codes see: click here

For signer status codes see: click here

The resource_uri refers to the relevant document or signer to which the name/value information will apply.

A useful status value is code '100’. This code is sent when a document is available for download. Use this code rather than (or in addition to ) status '30’ to confirm the document is available for download. There can be a lag between signing and document creation so use this code to be sure a document is both signed and ready for download.

Other notification names and values

Email bounces - 'bounce’

Unless you are using your own SMTP, email bounces are also in the callback. The resource_uri refers to the relevant signer. The name is 'bounce’ and the value indicates the nature of the error.

Storage retrievals - 'storage_retrieval’

After a while signed PDFs are put in long term storage. It can take 4 hours or so to retrieve these documents. If you attempt to download a document in storage you will receive a 202 HTTP code from the /pdf/ endpoint. When the document is available you will be notified in the callback. The resource_uri will be the relevant document reference, name will be 'storage_retrieval’ and value will be 'completed’. You will of course never need this since you will have downloaded and backed-up your documents before we moved it into long-term storage, right..?

N.B. your code should anticipate that the callback could be used further forms of notification and that different strings in 'name’ and 'value’ could be added at a later date.

Validate

You can use the 'signed’ string to verify the message comes from us by using (i) the sent data (make sure you encode it into a JSON string), (ii) the signed string and (iii) this X509 certificate::

—–BEGIN CERTIFICATE—– MIIFSjCCAzICAQAwDQYJKoZIhvcNAQEFBQAwazEeMBwGA1UEBxMVRWRpbmJ1cmdo LFNjb3RsYW5kLEdCMRswGQYDVQQKExJMZWdhbGVzaWduIExpbWl0ZWQxLDAqBgNV BAMUI2xlZ2FsZXNpZ24uY29tL2VtYWlsQGxlZ2FsZXNpZ24uY29tMB4XDTEzMDIw MTE2MjgyN1oXDTMzMDIwMTE2MjgyN1owazEeMBwGA1UEBxMVRWRpbmJ1cmdoLFNj b3RsYW5kLEdCMRswGQYDVQQKExJMZWdhbGVzaWduIExpbWl0ZWQxLDAqBgNVBAMU I2xlZ2FsZXNpZ24uY29tL2VtYWlsQGxlZ2FsZXNpZ24uY29tMIICIjANBgkqhkiG 9w0BAQEFAAOCAg8AMIICCgKCAgEAyzOOqZJ0BnwhJyOSBj1P3W7EGouKe0M1KFif CEm9jlw1q5iKupOnbqJRAKG+znDTeocFfwywnQnz7b6AfZ33QiR/HYFJT4J+3HCO 186VUNsXcK3KtJxfIhsO03zFfIaoRmXLkwaUJlP2dfGc10PNX6EBYyqzRG6TzlB6 uNdb3R/EeSTMn+VVyZ8E/L1ujeAFW8nZ+V8xAdvqSSeP3tMHwcRq1u6Mk9DUdlhs dL//sdTEkNar3FJAlisvXlLs6deXSLsIfr8g6K/59g0HsCEvRKqVa0WFs4OpPR3q dN+0PecON0pU6tRuN+9TTsss3hzjRfijiiktLaAIKZrupZDPZ9gSb5bfwL6zjdTN y3TTb/SzNZ1agwRoqftOAfff9ffCNUSrtQr4g3isGgtj2jQQ/W7+yFvEGGqy9/Co inlaNJqJPYdfYhwJ30sihTkKKzIcUKRGvrnW7QlIl+6+QMToCGql1AbVG1CIQeiP NkAmsQxieGrE0OszG1mTx1+SmBGo7WV32iV6sjmaOGHdE9zeNjRSJRS/SIWY8V+b 2i2W7zi3DvziRPqg6LUJX2pgAuDUmTxg6gMEzh8HHT36igzainrkKXqqoBsqwttY OikzGBBcctlhyWApgNqKi953S6dvEMsjWuyzqaYTn4QkQZnfZaIHj8KVQOI3cCgD 6m8BjTMCAwEAATANBgkqhkiG9w0BAQUFAAOCAgEARHEUsvB7aa+/hp1dR6bqaR0W bigK3Xm8LLB7PR0AjojOW1TUUDQLFKkHayqMNB0jcML/7Np4dGhOuAB6hfaq09hw xLexhix9DXgnm89QPzClHDTHzcbB2sqhqZKRlsJXfW3Dsh3iN9QdWt341ZsmaPBi gPvJpzKCoG4FhUsXUwCKERh41xssPsg7c417+OnU15I63bb4SlGH9+6j4kHGZh7p 2Sxn27CC4tDLGkI6fOVZapmN1iM+x17n/GCOTDrqlGXw72u0xH3yUA8W75HyuL31 m/6jlO9VQfY7ZVJn9IuoFjX+sU3uTz7PZhqFHLi2M4hVSaRgJ5JZBkUtr2eTvvhL iPBwjOfdba4rulqVni7joN1k4ulYnrpf6jmC/sbUPQkU9HbAUOhibyLEkysEhUPb 78aFbM+4c6rhzSRL5gvN7lVmBTZimmIs0x5y+Q5+GSIrRZgHkSxOGkrQtdsrJStg zerSTb5dF+L9Jv0d2AhIWMLP4KIO4NMj/ljiPOwtqPHU2KSsRivJA1xybFI4peBE aAocb936W/RabYdVCPITLsYA4ThApMI+jpJPvG8JKTrauOwZRBOq82lBJuoBgkAp h6A3SPeR5GCnCRmPIvrv21Q7dm7Gg4lbPtEemH3QdNlCIY1BzADD/H1zDAU+0J5P +PUQCjWRM3JmFbuYTjs= —–END CERTIFICATE—–

The language you’re using should have PKI library you can use to validate the signature using those three pieces of information.

/sandbox/ - Option 1 sandbox

While you’re in sandbox mode you can create fake notifications to send to your notification url.

Send an authorized GET request to the /sandbox/ endpoint, and add 'resource_uri’ and 'value’ to the querystring.

'resource_uri’ can be any resource_uri string and value should be an integer. A typical resource_uri might look like ’/api/v1/document/[doc-id]/ and a value might be '30’.

The callback URL could receive either a document or a signer resource_uri to indicate a change in status for either of those. For possible status codes go to: Document Status Codes.

Option 2. Realtime update when a document is signed

Example of the POST that will be sent to you

    {
      "resource_uri": "/api/v1/document/[doc-id]/",
      "group": "/api/v1/group/your-group/",
      "name": "name of doc",
      "uuid": "[doc-id]"
    }

Whenever a document is signed you’ll get a POST containing the resource URI, group, name of document and its id. This is just a regular POST dictionary, it is not a JSON object.

(If you used the API to create the document in the first place, the status resource_uri of the document is included in the 'Location’ header of the 201 'created’ response.)

Text Templates

Text Templates are re-usable stored documents in HTML format.

Text background

Fields

Fields are SPAN element written into the source of your document to define where you want to put signatures and form fields for the signer(s).

The easiest way to familiarise yourself with fields is to create a template using different field types in the web interface and inspect the HTML. The attributes are:

SPAN attribute Type Description
class string must always have the value ‘field’
data-signee integer the signer to which the field applies (start from 1) - see note below
data-name string label for the field e.g. Please sign here
data-optional bool true/false - require the field to be completed by the signer
data-type string can be 'text’,'select’ or 'signature’, text is a plain text field and select is a list
data-options string if using 'select’ data-type, add the drop down options delimited with ’^’, e.g. yes^no

If you see other options in Legalesign source code you can ignore them these are added by us later.

data-type 'signature’ note: add this where you want to place a signature. If you use this data-type make sure you have at least one for each signer. If you do not use this data-type check the 'signature_placement’ document option for adding signatures automatically.

data-signee note: confusingly the signer order is zero-indexed when you POST to the document endpoint, but 1-indexed in these text fields. Thus text fields where you write 'data-signee=1’ refer to the signer with order '0’ in other parts of the API. Sorry about that.

If you want to add/edit Legalesign text/html templates in a WYSIWYG you may find it helpful to use the tinymce fields plugin at https://bitbucket.org/legalesign/tinymce_field.

Images (HTML/Text documents)

Images placed in a html/text document MUST (a) be linked from a secure HTTPS server, you should not use HTTP, (b) and they must have width and height attributes.

Attributes

POST, PATCH attributes for a template

attribute required default type max length
user Y resource_uri
group Y resource_uri
title Y string 60
latest_text Y string
signee_count N 2 integer
archive N False bool
comment* N string 250

*comment is used for version control and can be added when sending data to server, but it is not returned in GET requests.

template/

Text templates to which the user has access. By default only unarchived templates will be returned, you can use the filters below to return archived or all documents

Example of a POST using curl

    curl --dump-header - -H "Content-Type: application/json"
    -H "Authorization: [auth_code]"
    -X POST --data '{ "user": "/api/v1/username/[sample]/", "group": "/api/v1/group/your-group/",  "latest_text": "[text here]",
    "title": "a title",  "comment": "initial draft" }' https://api.legalesign.com/api/v1/template/

Allowed methods: GET, POST

Filters - use in the querystring to filter by archive status or group:

> Example of a GET response in JSON

    {
      "meta": {
        "limit": 20, 
        "next": null, 
        "offset": 0, 
        "previous": null, 
        "total_count": 2
      }, 
      "objects": [
            {
              "archive": false, 
              "created": "2016-12-06T17:49:46", 
              "group": "/api/v1/group/your-group/", 
              "has_fields": false, 
              "modified": "2016-12-06T17:49:46", 
              "resource_uri": "/api/v1/template/[template-id]/", 
              "signee_count": 2, 
              "title": "Doc Title", 
              "uuid": "[template-id]"
            }, 
            {
              "archive": false, 
              "created": "2016-12-06T17:49:46", 
              "group": "/api/v1/group/your-group/", 
              "has_fields": false, 
              "modified": "2016-12-06T17:49:46", 
              "resource_uri": "/api/v1/template/[template-id]/", 
              "signee_count": 2, 
              "title": "Doc Title 1", 
              "uuid": "[template-id]"
           }
        ]
      }

template/[template-id]/

A single template, includes the latest text.

Allowed methods: GET, PATCH, DELETE

Example of a GET response in JSON

    {
      "archive": false, 
      "created": "2016-12-06T17:49:46", 
      "group": "/api/v1/group/your-group/", 
      "has_fields": false, 
      "latest_text": "<p>text here</p>", 
      "modified": "2016-12-06T17:49:46", 
      "resource_uri": "/api/v1/template/[template-id]/", 
      "signee_count": 2, 
      "title": "Doc title", 
      "uuid": "[template-id]"
    }

Example of a PATCH using curl

    curl --dump-header - -H "Content-Type: application/json"
    -H "Authorization: [auth_code] -X PATCH
    --data '{ "user": "/api/v1/username/[sample]/", "group": "/api/v1/group/your-group/",
    "latest_text": "[doc text here]", "title":"doc title"}' https://api.legalesign.com/api/v1/template/[template-id]/

PDF Templates

templatepdf/

PDF templates to which the user has access. By default only unarchived templates will be returned, use the filters as per /template/ to retrieve archived versions.

Allowed methods: GET, POST

A POST using curl. The PDF file itself should be base64 encoded string.

    curl --dump-header - -H "Content-Type: application/json"  -H "Authorization: [auth_code]"
    --data '{"group":"/api/v1/group/your-group/", "title":"Uploaded PDF",
     "pdf_file": "<base64 encoded string of file data>"}'  -X POST https://api.legalesign.com/api/v1/templatepdf/

The PDF creator will the API key holder. If you need to create a PDF and assign its creator attribute to another group member contact us.

A GET call will return your unarchived pdf templates. A POST call will upload a new PDF.

Tip - to avoid uploading a lot of PDFs, use a generic document and then make use of ‘sender’ fields to add custom information to the PDF each time you send it.

Attribute Type Required Description
group resource_uri Y the relevant group
pdf_file string Y base64 encoded string of file data
title string N document title
process_tags boolean N (POST only) Automatically process any tags to create fields

Adding fields

Use the process_tags attribute to process any text tags upon upload. You can also use the /tags/ endpoint below. We recommend avoiding process_tags however and using the /tags/ endpoint after uploading. For more information about text tags click here. Otherwise you can add fields using co-ordinates at the /fields/ endoint. When using text tags query the fields endpoint to sanity check your fields have been properly processed.

templatepdf/[pdf-id]/

JSON response to a query for a template pdf - note the 'valid’ key::

{
  "created": "2016-12-06T17:49:46", 
  "group": "/api/v1/group/your-group/", 
  "modified": "2016-12-06T17:49:46", 
  "page_count": 8, 
  "resource_uri": "/api/v1/templatepdf/[pdf-id]/", 
  "title": "Deal or No Deal", 
  "user": "/api/v1/username/[sample]/", 
  "uuid": "[pdf-id]", 
  "valid": true
}

Allowed methods: GET

Returns details in connection with a single PDF document. In particular you need a PDF to be valid in order to send it. After you create your form fields call this endpoint to check the PDF validity.

The validity of a PDF depends on its form fields. It needs at least 1 signature field. A document will not be valid if its form fields do not make sense, for example, if you have form fields for signer 2 but no signature field.

templatepdf/[pdf-id]/tags/

Allowed methods: POST

Process any tags in the document. This will delete any existing fields.

Query to the /fields/ endpoint to make sure your tags have been processed properly.

For more information about text tagging click here.

templatepdf/[pdf-id]/fields/

Field data associated with a PDF templates (signatures, initials, signer fields and sender fields (called 'admin’ fields in the API)).

Allowed methods: GET, POST

Use a GET request to return listings of existing form fields. Use a POST to create a new set of form fields. You will have to POST a new set of form fields after you upload a new PDF.

If creating a field read this section carefully:

POST JSON dictionary


POST data for a form field might look like this - remember to use a list object in the event you are creating many form fields:

[{ "fieldorder":1, "group": "/api/v1/group/your-group/", "signer": 1, "element_type": "signature", "page": 1, "ax":0.2, "ay":0.2, "bx":0.4,"by":0.25 }]

POST data should be a list of hash dictionaries that each specify a form field using the attributes below. A POST will obliterate all existing form fields and create a new set from your POSTED data. Changing form fields will not affect any documents already sent using that PDF.

The positioning of a field is determined by the keys 'ax’,'ay’,'bx’ and 'by’. 'ax’ and 'bx’ refer to the left and right horizontal edges respectively, while 'ay’ and 'by’ refer to the upper and lower vertical edges.

The positioning float numbers indicate distance from the left (for ax, bx) and top (for ay, by) of the document, where 0 is the left and top edge and 1 is the right and bottom edge.

GET reponse with field objects - not page and signer integers are 1 indexed.



A GET response

{
  "meta": {
    "limit": 20, 
    "next": null, 
    "offset": 0, 
    "previous": null, 
    "total_count": 2
  }, 
  "objects": [
    {
      "ax": 0.160112359550562, 
      "ay": 0.114200595829196, 
      "bx": 0.39747191011236, 
      "by": 0.162859980139027, 
      "element_type": "signature", 
      "font_size": 12, 
      "label": "", 
      "label_extra": "", 
      "optional": false, 
      "page": 1, 
      "signer": 1, 
      "substantive": true, 
      "validation": null
    }, 
    {
      "ax": 0.47478993733724, 
      "ay": 0.163181361641709, 
      "bx": 0.674743242659368, 
      "by": 0.203584394347358, 
      "element_type": "text", 
      "font_size": 12, 
      "label": "", 
      "label_extra": "", 
      "optional": false, 
      "page": 1, 
      "signer": 1, 
      "substantive": true, 
      "validation": null
    }
  ]
}
Attribute Type Required Description
ax float Y horizontal left
bx float Y horizontal right
ay float Y vertical top
by float Y vertical bottom
fieldorder integer Y The ordering for fields if more than one per page
signer integer Y 1-indexed number to assign field to a signer
element_type string Y possible values: signature, initials, text (signer field), admin (sender field)
page integer Y
label string Y max length 60
label_extra string N If 'label’ is just not long enough. max length 250.
font_size integer N min 6, max 20
substantive bool N whether a signer field is required before document can be signed by another party
validation integer N For signer form fields. Specify a type of input or format. See list of possible values below
optional integer N default false (i.e. not optional - required by default)
options list N If you select 'dropdown’ validation add a list of options (max length 30 each line).

Possible validation values (for signer form fields):

Value Explanation
1Email
2 yyyy/mm/dd
3 yy/mm/dd
4 dd/mm/yyyy
5 dd/mm/yy
6 mm/dd/yyyy
7 mm/dd/yy
8 yyyy.mm.dd
9 yy.mm.dd
10 dd.mm.yyyy
11 dd.mm.yy
12 mm.dd.yyyy
13 mm.dd.yy
14 yyyy-mm-dd
15 yy-mm-dd
16 dd-mm-yyyy
17 dd-mm-yy
18 mm-dd-yyyy
19 mm-dd-yy
20 Dropdown list. See 'options’ attribute.
21 Yes/No
24 ✔/✗
25 ✔/blank
26 ✗/blank
30 yyyy/mm/dd (auto sign day)
31 yy/mm/dd (auto sign day)
32 dd/mm/yyyy (auto sign day)
33 dd/mm/yy (auto sign day)
34 mm/dd/yyyy (auto sign day)
35 mm/dd/yy (auto sign day)
36 yyyy.mm.dd (auto sign day)
37 yy.mm.dd (auto sign day)
38 dd.mm.yyyy (auto sign day)
39 dd.mm.yy (auto sign day)
40 mm.dd.yyyy (auto sign day)
41 mm.dd.yy (auto sign day)
42 yyyy-mm-dd (auto sign day)
43 yy-mm-dd (auto sign day)
44 dd-mm-yyyy (auto sign day)
45 dd-mm-yy (auto sign day)
46 mm-dd-yyyy (auto sign day)
47 mm-dd-yy (auto sign day)
48 d mmmm yyyy (auto sign day)
50 Whole number
51 Number
52 Currency (2 decimal points)
53 1 number
54 2 numbers
55 3 numbers
56 4 numbers
57 5 numbers
58 6 numbers
59 7 numbers
60 8 numbers
61 9 numbers
62 10 numbers
63 11 numbers
64 12 numbers
65 1 character (any text)
66 2 characters (any text)
67 3 characters (any text)
68 4 characters (any text)
69 5 characters (any text)
70 6 characters (any text)
71 7 characters (any text)
72 8 characters (any text)
73 Secret code - add code in options
74 File attach - append to confirmatory email to signer (ensure the group setting to send this email is on)
75 File attach - append to final PDF (appends uploaded files to final PDF)

Groups

Groups are collections of templates, documents and users (members). You can have as many templates, documents and users as you like in a group.

group/

Return list of groups the API user belongs to.

Allowed methods: GET, POST

Example of a GET response in JSON::

  {
  "meta": {
    "limit": 20, 
    "next": null, 
    "offset": 0, 
    "previous": null, 
    "total_count": 14
  }, 
  "objects": [
    {
      "created": "2016-12-06T17:49:46",
      "is_active": true,
      "modified": "2016-12-06T17:49:46", 
      "name": "Your Group", 
      "resource_uri": "/api/v1/group/your-group/", 
      "slug": "your-group"
    }, 
    ]
    }

If you haven’t reached your account limit on groups, you can create more::

    curl --dump-header - -H "Content-Type: application/json"
    -H "Authorization: [auth_code]"
    -X POST --data '{ "name": "Group on" }' https://api.legalesign.com/api/v1/group/

If you attempt to add more groups than your account is limited to you’ll receive a 400 response with the following data::

{ “group”: { “plan”: “Please upgrade to add more groups, or deactivate a current group to add another” }

There is no DELETE for groups. If you have a redundant group set its is_active attribute to false. You’ll be able to add groups to replace them.

group/[group-id]/

Return a group details, including members.

Allowed methods: GET, PATCH

Example of a GET response in JSON

     {
    "created": "2016-12-06T17:49:46", 
    "default_email": "",
    "default_extraemail": "", 
    "footer": "<p>Legalesign</p>", 
    "footer_height": 110, 
    "header": null, 
    "header_height": null,
    "is_active": true, 
      "members": [
        "/api/v1/user/[user-id]/", 
        "/api/v1/user/[another-user-id]/"
      ], 
      "modified": "2016-12-06T17:49:46", 
      "name": "Your Group", 
      "pagesize": 1,  //PDF page size, 1 = A4 (only available currently)
      "resource_uri": "/api/v1/group/your-group/", 
      "slug": "your-group"
    } 

Attributes available for PATCH

Example of a PATCH in curl::

    curl --dump-header - -H "Content-Type: application/json"  -H
    "Authorization: [auth_code]"
    -X PATCH --data '{ "name":"New name", "default_email": "A new default email" }'
    https://api.legalesign.com/api/v1/group/your-group/
Attribute Type Notes
name string maxlength 60, minlength 3
footer string html for text at the footer of each PDF page
default_email string maxlength 1000
default_extraemail string maxlength 2000
footer_height integer pixel height for footer on pdf, 1px = 0.025cm
header string html for text at the head of each PDF page
header_height integer pixel height for header on pdf, 1px = 0.025cm
is_active bool shut down/turn on a group.
pagesize integer must be 1, more options coming soon

Once header and footer are saved to a group you can use them in text documents by using the keyword ‘default’ in the header and footer attributes when creating a new document.

N.B. Since this is a PATCH, only the attributes sent to the server are updated. If this was sent as a PUT request it would have also updated the other attributes that are not sent to null.

Members

Add, list or remove members from groups.

member/

Allowed methods: GET, POST

The GET method will return all the members of all the groups the API user belongs to.

Filter by group by adding a group parameter to the querystring. Use either the group url name or the group resource_uri, e.g. ?group=your-group or ?group=/api/v1/group/your-group/

Example of a GET response in JSON::

    {
    "meta": {
    "limit": 20, 
    "next": null, 
    "offset": 0, 
    "previous": null, 
    "total_count": 2
    }, 
    "objects": [
    {
      "created": "2016-12-06T17:49:46", 
      "group": "/api/v1/group/your-group/", 
      "modified": "2016-12-06T17:49:46", 
      "resource_uri": "/api/v1/members/[members-id]/", 
      "user": "/api/v1/username/[sample]/"
    }, 
    {
      "created": "2016-12-06T17:49:46", 
      "group": "/api/v1/group/another-group/", 
      "modified": "2016-12-06T17:49:46", 
      "resource_uri": "/api/v1/members/[members-id]/", 
      "user": "/api/v1/username/[sample]/"
    }
    ]
    }

POST adds another person to a group, it should contain the group (full resoure uri), email and permission of person who will join. For permissions please see table in ‘users’ section.

Example of POST in curl

    curl --dump-header - -H "Content-Type: application/json"
    -H "Authorization: [auth_code]"
    -X POST --data '{  "group": "/api/v1/group/your-group/",
    "email": "test@example.com", "do_email": true }'
    https://api.legalesign.com/api/v1/member/

If the person is not an existing user, it will be preferable to use the /user/ endpoint where you can create a new user and add the person to your group(s) in one call.

Attributes Type Description
group resource_uri group you want person to join
email email email of person to join
do_email bool default=false, use legalesign to send email notification to new member

If the person is already a member of Legalesign they will join the group immediately. If they are not signed up already they will be 'invited’. See below for more information on /invited/ endpoint below.

Errors will be returned with a 400 response and a description of the error in the BODY.

BODY of response if person has already joined::

    {
    "member": {
      "exists": "User is already a member of this group"
    }

BODY of response if person has already been invited (but not signed up to Legalesign yet)::

    {
    "member": {
    "invited": "User has been invited to join, but has not yet signed up"
    }

member/[member-id]/

Allowed methods: GET, DELETE

DELETE will remove the member from the group. To add the person back to the group POST their email to the /member/ endpoint, as above.

invited/

Example GET response in JSON:

    {
    "meta": {
    "limit": 20, 
    "next": null, 
    "offset": 0, 
    "previous": null, 
    "total_count": 1
    }, 
    "objects": [
    {
      "created": "2016-12-06T17:49:46", 
      "email": "test@example.com", 
      "group": "/api/v1/group/your-group/", 
      "resource_uri": "/api/v1/invited/[invited-id]/"
    }
    ]
    }

List all people who have been invited to joined groups the API user belongs to. Invitations are created when the person you add to a group has no account on Legalesign. Once they create an account they will become a member of the group.

Filter by group by adding a group parameter to the querystring. Use either the group url name or the group resource_uri, e.g. ?group=your-group or ?group=/api/v1/group/your-group/

Allowed methods: GET

invited/[invited-id]/

Allowed methods: DELETE

Remove the invitation. When the person signs in they will not be made a member of the group.

Users

user/

Create a new user who can gain access to your groups. You should specify the groups the user should be able to access. Only groups the API user can access are valid.

If you do not set a password then a verification link will be emailed to the user. This will allow the user to set their password and activate their account. In this case you can also add a redirect_to url to redirect the user back to your website after they have activated their account.

N.B. Make sure you add the user to at least one of your groups, otherwise you will not have API access to the user information.

Allowed methods: POST

Attribute Type Required Notes
first_name string Y maxlength=30
last_name string Y maxlength=30
email email Y
timezone timezone Y must be from list below
password string N if not used, a verification link is emailed for the user to set their password
redirect_to url N if verification link is emailed, a redirect upon success, defaults to legalesign web app.
groups string N comma-delimited list of groups for user to join, can be url name or resource_uri
permission integer N one of permissions from list below, if blank defaults to ‘admin’

Permissions:

Integer Explanation
1 Admin
2 Create and send docs (team user - can see other sent and uploaded/saved docs)
3 Readonly (team user - can see other docs)
4 Send only (team user)
5 Send only (individual user - cannot see other sent docs, but shares in uploaded/saved docs)
6 Create and send docs (individual user - cannot see any other user activity)

Please note that individual users can affect pricing, contact us for more information

user/[user-id]/

Example of a GET response in JSON

    {
      "date_joined": "2016-12-06T17:49:46", 
      "email": "", 
      "first_name": "Joe", 
      "groups": [
        "/api/v1/group/your-group/", 
      ], 
      "last_login": "2016-12-06T17:49:46", 
      "last_name": "Bloggs", 
      "resource_uri": "/api/v1/username/[sample]/", 
      "timezone": "UTC", 
      "username": "[username]"
    }

Return the user’s details, including list of groups the user belongs to. The API user can access their own details and any user belonging to the same groups the API user has joined.

Allowed methods: GET, PATCH

Attributes available for PATCH

Attribute Type Notes
first_name string maxlength 30, required
last_name string maxlength 30, required
timezone timezone see list of recognised timezones below, required

Timezones:

You got to the end. Nice work.