Blog
Home/

Common API Tasks🐈: Parsing an envelope's audit events

Inbar Gazit
Inbar GazitSr. Manager, Developer Content
Summary3 min read

Parse audit events in your envelopes' history with the eSignature REST API to find corrections and downloads.

    • C#
    • Java
    • Node.js
    • PHP
    • Python
    • Ruby
    • Additional resources

    Table of contents

    Common API Tasks: Parsing an envelope's audit events

    Welcome to another edition of the CAT🐈 (Common API Tasks) blog. This blog series is about giving you all you need to complete small, specific, SDK-supported tasks using one of our APIs. You can find all articles in this series on the Docusign developer blog. 

    Did you know that Docusign keeps track of any and all activity related to each envelope that is sent in the Docusign Agreement Cloud? For many important reasons, the system keeps a detailed audit trail for each envelope. You can find this information in the web app by selecting the History option (also available in the signing UI). Many important activities in an envelope’s lifecycle are recorded as audit events, including when the envelope was created, sent, opened for viewing, signed, and more. You can get the entire audit trail by using a single API call and then parse it to find useful information. 

    In this blog post I’ll show code snippets to find out if an envelope was corrected as well as if it was downloaded. This is done by looking over all the events in the envelope’s audit history and searching for the specific events telling us that the envelope was either corrected or downloaded (there are two events for downloading an envelope, depending on whether the user downloaded a ZIP file with all documents, or just downloaded specific documents). If I find the envelope was corrected or downloaded, I’ll report about when it was done and by whom (which user). Note that this is simple code and I didn’t address the possibility that an envelope was corrected or downloaded multiple times. You can enhance this code to deal with more complex situations, as well as look for other events that may interest you.

    Important note: This particular API call is resource-intensive and has a performance impact; use it only when needed.

    And without further ado, here are the code snippets for our six SDK languages:

    C#

    // You need to obtain an access token using your chosen authentication flow
    var apiClient = new ApiClient(basePath);
    apiClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + accessToken);
    EnvelopesApi envelopesApi = new EnvelopesApi(apiClient);
    var audit = envelopesApi.ListAuditEvents(accountId, envelopeId);
    foreach (var auditEvent in audit.AuditEvents)
    {
        bool corrected = false;
        bool downloaded = false;
        string userName = "";
        string logTime= "";
        foreach (var auditField in auditEvent.EventFields)
        {
            if (auditField.Name == "UserName")
            {
    userName = auditField.Value;
            }
            else if (auditField.Name == "logTime")
            {
    logTime = auditField.Value;
            }
            else if ((auditField.Name == "Action") && (auditField.Value == "Corrected"))
            {
    corrected = true;
            }
            else if ((auditField.Name == "Action") && ((auditField.Value == "Printable Copy Delivered") || (auditField.Value == "Archive Delivered")))
            {
    downloaded = true;
            }
        }
        if (corrected)
        {
            Console.WriteLine($"Envelope was corrected by {userName} on {logTime}");
        }
        if (downloaded)
        {
            Console.WriteLine($"Envelope was downloaded by {userName} on {logTime}");
        }
    }
    
    

    Java

    // You need to obtain an access token using your chosen authentication flow 
    Configuration config = new Configuration(new ApiClient(basePath));
    config.addDefaultHeader("Authorization", "Bearer " + accessToken);
    EnvelopesApi envelopesApi = new EnvelopesApi(config);
    EnvelopeAuditEventResponse audit = envelopesApi.ListAuditEvents(accountId, envelopeId);
    for (EnvelopeAuditEvent auditEvent : audit.getAuditEvents())
    {
        boolean corrected = false;
        boolean downloaded = false;
        string userName = "";
        string logTime= "";
        for (NameValue auditField : auditEvent.getEventFields())
        {
            if (auditField.getName() == "UserName")
            {
    userName = auditField.getValue();
            }
            else if (auditField.getName() == "logTime")
            {
    logTime = auditField.getValue();
            }
            else if ((auditField.getName() == "Action") && (auditField.getValue() == "Corrected"))
            {
    corrected = true;
            }
            else if ((auditField.getName() == "Action") && ((auditField.getValue() == "Printable Copy Delivered") || (auditField.getValue() == "Archive Delivered")))
            {
    downloaded = true;
            }
        }
        if (corrected)
        {
            System.out.println("Envelope was corrected by " + userName + " on " + logTime);
        }
        if (downloaded)
        {
            System.out.println("Envelope was downloaded by " + userName + " on " + logTime);
        }
    }
    
    

    Node.js

    // You need to obtain an access token using your chosen authentication flow 
    let dsApiClient = new docusign.ApiClient();
    dsApiClient.setBasePath(basePath);
    dsApiClient.addDefaultHeader('Authorization', 'Bearer ' + accessToken);
    let envelopesApi = new docusign.EnvelopesApi(dsApiClient);
    let audit = envelopesApi.listAuditEvents(accountId, envelopeId);
    audit.auditEvents.forEach (auditEvent =>
    {
        let corrected = false;
        let downloaded = false;
        auditEvent.eventFields.forEach(auditField =>
        {
            if (auditField.name === 'UserName')
            {
    userName = auditField.Value;
            }
            else if (auditField.name === 'logTime')
            {
    logTime = auditField.value;
            }
            else if ((auditField.name === 'Action') && (auditField.value === 'Corrected'))
            {
    corrected = true;
            }
            else if ((auditField.name === 'Action') && ((auditField.value === 'Printable Copy Delivered') || (auditField.value === 'Archive Delivered')))
            {
    downloaded = true;
            });
        });
        if (corrected)
        {
            console.log('Envelope was corrected by ' + userName + ' on ' + logTime);
        }
        if (downloaded)
        {
            console.log('Envelope was downloaded by ' + userName + ' on ' + logTime);
        }
    }
    
    

    PHP

    # You need to obtain an access token using your chosen authentication flow 
    $api_client = new \Docusign\eSign\client\ApiClient($base_path);
    $config = new \Docusign\eSign\Model\Configuration($api_client);
    $config->addDefaultHeader('Authorization', 'Bearer ' + $access_token);
    $envelopes_api = new \Docusign\Api\EnvelopesApi($config);
    $audit = $envelopes_api->listAuditEvents($account_id, $envelope_id);
    $audit_events = $audit->getAuditEvents();
    foreach ($audit_event as $audit_events)
    {
        $corrected = false;
        $downloaded = false;
        $audit_fields = $audit_event->getEventFields();
        foreach ($audit_field as $audit_fields)
        {
            if ($audit_field->getName() == 'UserName')
            {
    $user_name = $audit_field->getValue();
            }
            elseif ($audit_field->getName() == 'logTime')
            {
    $log_time = $audit_field->getValue();
            }
            elseif (($audit_field->getName() == 'Action') && ($audit_field->getValue() == 'Corrected'))
            {
    $corrected = true;
            }
            elseif (($audit_field->getName() == 'Action') && (($audit_field->getValue() == 'Printable Copy Delivered') || ($audit_field->getValue() == 'Archive Delivered')))
            {
    $downloaded = true;
            }
        }
        if ($corrected)
        {
            printf('Envelope was corrected by ' + $user_name + ' on ' + $log_time);
        }
        if ($downloaded)
        {
            console.log('Envelope was downloaded by ' + $user_bame + ' on ' + $log_time);
        }
    }
    

    Python

    # You need to obtain an access token using your chosen authentication flow 
    api_client = ApiClient()
    api_client.host = base_path
    api_client.set_default_header('Authorization', 'Bearer ' + access_token)
    envelopes_api = EnvelopesApi(api_client)
    audit = envelopes_api.list_audit_events(account_id, envelope_id)
    for audit_event in audit.audit_events:
        corrected = false
        downloaded = false
        for audit_field in audit_fields.event_fields:
            if audit_field.name == 'UserName' :
    user_name = audit_field.value
            elif audit_field.name == 'logTime' :
    log_time = audit_field.value
            elif (audit_field.name == 'Action') && (audit_field.value == 'Corrected') :
    corrected = true
            elif (audit_field.name == 'Action') && ((audit_field.value == 'Printable Copy Delivered') || (audit_field.value == 'Archive Delivered')) :
    downloaded = true
        if corrected :
            print('Envelope was corrected by ' + user_name + ' on ' + log_time)
        if downloaded :
            print('Envelope was downloaded by ' + user_bame + ' on ' + log_time)
    
    

    Ruby

    # You need to obtain an access token using your chosen authentication flow 
    config = DocuSign_eSign::Configuration.new
    config.host = base_path
    api_client = DocuSign_eSign::ApiClient.new config
    api_client.DefaultHeader['Authorization'] = 'Bearer ' + access_token
    envelopes_api = DocuSign_eSign::EnvelopesApi.new api_client
    audit = envelopes_api.list_audit_events(account_id, envelope_id)
    audit.audit_events.each do |audit_event|
    {
        corrected = false
        downloaded = false
        audit_fields.event_fields.each do |audit_field|
        {
            if audit_field.name == 'UserName' 
    user_name = audit_field.value
            elsif audit_field.name == 'logTime' 
    log_time = audit_field.value
            elsif (audit_field.name == 'Action') && (audit_field.value == 'Corrected') :
    corrected = true
            elsif (audit_field.name == 'Action') && ((audit_field.value == 'Printable Copy Delivered') || (audit_field.value == 'Archive Delivered')) 
    downloaded = true
        }
        if corrected 
            printf('Envelope was corrected by ' + user_name + ' on ' + log_time)
        if downloaded :
            printf('Envelope was downloaded by ' + user_bame + ' on ' + log_time)
    }
    
    

    That’s it for today’s edition... I hope you found it useful. If you have any questions, comments, or suggestions for topics for future Common API Tasks posts, feel free to email me. Until next time...

    Additional resources

    Inbar Gazit
    Inbar GazitSr. Manager, Developer Content

    Inbar Gazit has been with Docusign since 2013 in various engineering roles. Since 2019 he has focused on developer content. Inbar works on code examples including the launchers, available on GitHub in eight languages, and helps build sample apps showcasing the various Docusign APIs. He is also active on StackOverflow, answering your questions. Inbar can be reached at inbar.gazit@docusign.com.

    More posts from this author

    Related posts

    • Common API Tasks

      Common API Tasks🐈: List all your Maestro workflows using the Maestro API

      Inbar Gazit
      Inbar Gazit
    • Common API Tasks🐈: Find a web form by name

      Common API Tasks🐈: Find a web form by name

      Inbar Gazit
      Inbar Gazit
    Common API Tasks🐈: Find a web form by name

    Common API Tasks🐈: Find a web form by name

    Inbar Gazit
    Inbar Gazit

    Discover what's new with Docusign IAM or start with eSignature for free

    Explore Docusign IAMTry eSignature for Free
    Person smiling while presenting