REST API

Getting Started

This tutorial talks about how to set up a Vault user account that has API access and walks through the basics of uploading a document to Vault.

Authentication

To make API calls against Vault, you need a Vault user account with API access. Once you have this, you can authenticate to get a session ID.

Vault User Account & Permissions

Your security profile and permission set may grant the following permissions:

Insufficient Access

If you do not have API access, your authentication request will succeed, but any other API calls you make will return the following error:

INSUFFICIENT_ACCESS: User [ID] not licensed for permission [VaultActions_API_Access].

If you do not have API access, contact your Vault administrator to adjust your security profile and permission set.

Structuring the Endpoint

As we talk about API calls, you’ll see the following variables in every endpoint. You’ll need to replace these with the correct values.

Get a Session ID

Your first API call will be an authentication request, which provides your session ID for other API calls. To do this, call the auth endpoint.

The auth endpoint (/api/{version}/auth) expects two URL-encoded form parameters (x-www-form-urlencoded): username and password.

Request

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" \
-d 'username={username}&password={password}' \
"https://{server}/api/{version}/auth"

This call returns a JSON response that contains the session ID.

Response

{
  "responseStatus": "SUCCESS",
  "sessionId": "3B3C45FD240E26F0C3DB4F82BBB0C15C7EFE4B29EF9916AF41AF7E44B170BAA01F232B462BE5C2BE2ACB82F6704FDA216EBDD69996EB23A6050723D1EFE6FA2B",
  "userId": 12021,
  "vaultIds": [
    {
      "id": 1776,
      "name": "PromoMats",
      "url": "https://promo-vee.veevavault.com/api"
    },
    {
      "id": 1782,
      "name": "Platform",
      "url": "https://platform-vee.veevavault.com/api"
    }
  ],
  "vaultId": 1776
}

Note: The vaultIds collection in the response is a list of available vaults. The vaultId field under this list tells you which vault you’ve authenticated against. Rarely, you can authenticate against the wrong vault if the intended vault is inactive. In this situation, you’ll authenticate against the last vault you accessed or the oldest vault in your domain. Check the vaultId against the information in the list to ensure that it’s the vault you intended.

Upload a Document

Now that you have a session ID, you can upload a document to your vault using the Documents API. In this example, you will create an unclassified document.

Assign the session ID to the header parameter Authorization. Specify the source file in the file body parameter. Since you will upload the document as unclassified assign the values Undefined and Unclassified to the body parameters type__v and lifecycle__v respectively.

Request

curl -X POST -H "Authorization: {SESSION_ID}" \
-H "Content-Type: multipart/form-data" \
-F file=@document.txt \
-F "name__v=myDocument" \
-F "type__v=Undefined" \
-F "lifecycle__v=Unclassified" \
https://{server}/api/{version}/objects/documents

If your request contains all the required metadata and your session ID is valid, the response includes a unique document ID. Note, the file document.txt resides in the directory from which the curl command is being executed.

Response

{
    "responseStatus": "SUCCESS",
    "responseMessage": "successfully created document",
    "id": 776
}

Note: On some application vaults you may have to set other parameters aside from type__v and lifecycle__v to successfully upload an unclassified document. If this is the case the API call will throw an exception and prompt you for the required fields.

Next Steps

Congratulations! You’ve successfully created your first document using Vault’s APIs. Once you’re ready, you can move on to the next tutorial where you’ll learn about document and object fields.

Understanding Metadata of Document & Object Fields

This tutorial covers how document and object fields work and how to use them when making API calls. We’ll also take a close look at some example fields and explain the semantics of their metadata attributes.

Vault Documents & Vault Objects

In Vault, “document” refers to both the files (source file, renditions, etc.) and the set of fields. An “object” is a kind of data entity, which also has a set of fields. Individual “object records” are instances of that data entity type with values assigned to the various fields. If you think of an object as a database table, each field is a column and each object record is a table row.

Learn more about vault objects and documents.

Document & Object Fields

When creating a document or an object record, there are some fields that you must specify and others that Vault itself populates. For example, you must specify a value for the Name field (name__v), but Vault itself generates a value for the id field. There are also fields that are editable and not required: you can create documents or object records without populating these.

Fields like id are known as “system-managed” fields and are often hidden in the UI. The id field is particularly important when using the API because you’ll use it to identify documents, object records, and other resources.

You can use the API to find all available fields on objects, for example:

Note these APIs will return blank values, but not null values. For example, when retrieving users, you may notice the last login field: "last_login__v": "2015-02-02T16:52:21.000Z". However, if a user never logged in, this field would be null and would not show up in the response at all. Fields with blank values, for example "office_phone__v": "", do appear in the response, showing the user has entered nothing for their office phone number.

When creating documents or object records through the API, the same field requirements and validation rules apply as when working through the UI.

Configuration Differences & Field Naming

Many fields defined on documents and objects for a given vault are unique to that vault’s configuration, meaning that the set of fields can be different between vaults. Some standard fields like name__v and id are common across all vaults. API requests use the field names, not labels. For example, the standard Product document field would be product__v.

The suffix on a field name indicates whether it’s standard or custom:

Metadata API

When using the APIs to create documents, query objects, etc., fields often serve as API parameters. Depending on the API, you may need to know the name of a field and if it’s queryable, editable, and/or required. All of this can be determined using the metadata APIs.

Metadata APIs define the shape of the fields on different document types, objects, or other resources. Below we’ll look at some key metadata properties to understand how Vault defines fields.

Document Metadata API

Let’s make an API call to get the fields defined on our documents.

Request

$ curl -X GET -H "Authorization: {SESSION_ID}" \ 
https://{server}/api/{version}/metadata/objects/documents/properties

Response

{
  "responseStatus": "SUCCESS",
  "properties": [
    {
      "name": "id",
      "type": "id",
      "required": true,
      "maxLength": 20,
      "minValue": 0,
      "maxValue": 9223372036854775807,
      "repeating": false,
      "systemAttribute": true,
      "editable": false,
      "setOnCreateOnly": true,
      "disabled": false,
      "hidden": true,
      "queryable": true
    },
    {
      "name": "version_id",
      "scope": "DocumentVersion",
      "type": "id",
      "required": true,
      "maxLength": 20,
      "minValue": 0,
      "maxValue": 9223372036854775807,
      "repeating": false,
      "systemAttribute": true,
      "editable": false,
      "setOnCreateOnly": true,
      "disabled": false,
      "hidden": true,
      "queryable": true
    },...
  ]
}

The API call above returns the entire list of fields defined on documents, across all document types. Each field itself has a list of metadata attributes that define its behavior and shape. The example shows only a short excerpt. A real response might include hundreds of fields.

Metadata of Document Fields

We’ll look at a few document fields to understand what the various metadata attributes mean.

id

The id is a special document field that Vault automatically assigns to uniquely identify each document.

 {
      "name": "id",
      "type": "id",
      "required": true,
      "maxLength": 20,
      "minValue": 0,
      "maxValue": 9223372036854775807,
      "repeating": false,
      "systemAttribute": true,
      "editable": false,
      "setOnCreateOnly": true,
      "disabled": false,
      "hidden": true,
      "queryable": true
 }

Name

{
      "name": "name__v",
      "scope": "DocumentVersion",
      "type": "String",
      "required": true,
      "maxLength": 100,
      "repeating": false,
      "systemAttribute": true,
      "editable": true,
      "setOnCreateOnly": false,
      "disabled": false,
      "label": "Name",
      "section": "generalProperties",
      "sectionPosition": 0,
      "hidden": false,
      "queryable": true,
      "shared": false,
      "helpContent": "Displayed throughout application for the document, including in Library, Reporting, Notifications and Workflows.",
      "definedInType": "type",
      "definedIn": "base_document__v"
}

Although it doesn’t need to be unique like id, name__v must also be populated for every document (required:true). This metadata attribute has a few interesting properties that didn’t appear on id.

Product

 {
      "name": "product__v",
      "scope": "DocumentVersion",
      "type": "ObjectReference",
      "required": false,
      "repeating": true,
      "systemAttribute": true,
      "editable": true,
      "setOnCreateOnly": false,
      "disabled": false,
      "objectType": "product__v",
      "label": "Product",
      "section": "productInformation",
      "sectionPosition": 1,
      "hidden": false,
      "queryable": true,
      "shared": false,
      "definedInType": "type",
      "definedIn": "base_document__v",
      "relationshipType": "reference",
      "relationshipName": "document_product__vr"
}

Some metadata attributes reference a specific object from the same vault. These attributes have the property type:ObjectReference. In this case, the product__v attribute references the product__v object. (The attribute name and the object name will not always be identical.) The values that you can assign to this attribute are the records within the Product object.

Object reference attributes have special properties:

Object Metadata API

Let’s make some API calls to get object metadata. First, we’ll get the list of objects defined in our vault.

Request

$ curl -X GET -H "Authorization: {SESSION_ID}" \ 
https://{server}/api/{version}/metadata/vobjects

Response

{
  "responseStatus": "SUCCESS",
  "objects": [
    {
      "url": "/api/v17.1/metadata/vobjects/product__v",
      "label": "Product",
      "name": "product__v",
      "label_plural": "Products",
      "prefix": "00P",
      "order": 2,
      "in_menu": true,
      "source": "standard",
      "status": [
        "active__v"
      ]
    },
    {
      "url": "/api/v17.1/metadata/vobjects/country__v",
      "label": "Country",
      "name": "country__v",
      "label_plural": "Countries",
      "prefix": "00C",
      "order": 4,
      "in_menu": true,
      "source": "standard",
      "status": [
        "active__v"
      ]
    }
  ]
}

From this response, we can see that there’s a Product object configured. Let’s call the metadata API for this object to see its fields. For this, we add the object name product__v to the request.

Request

$ curl -X GET -H "Authorization: {SESSION_ID}" \ 
https://{server}/api/{version}/metadata/vobjects/product__v

Response

{
  "responseStatus": "SUCCESS",
  "object": {
    ...
     "fields": [
      {
        "help_content": null,
        "editable": false,
        "lookup_relationship_name": null,
        "label": "ID",
        "source": "standard",
        "type": "ID",
        "modified_date": "2015-10-26T18:26:53.000Z",
        "created_by": 1,
        "required": false,
        "no_copy": true,
        "name": "id",
        "list_column": false,
        "modified_by": 1,
        "created_date": "2015-10-26T18:26:53.000Z",
        "lookup_source_field": null,
        "status": [
          "active__v"
        ],
        "order": 0
      },
      {
        "help_content": null,
        "editable": true,
        "lookup_relationship_name": null,
        "start_number": null,
        "label": "Product Name",
        "source": "standard",
        "type": "String",
        "modified_date": "2015-10-26T18:26:53.000Z",
        "created_by": 1,
        "required": true,
        "no_copy": false,
        "system_managed_name": false,
        "value_format": null,
        "unique": true,
        "name": "name__v",
        "list_column": true,
        "modified_by": 1,
        "created_date": "2015-10-26T18:26:53.000Z",
        "lookup_source_field": null,
        "status": [
          "active__v"
        ],
        "max_length": 128,
        "order": 1
      },
    ]
  }
}

Next Steps

Now that you understand how to read metadata attributes in your response, you’re ready to check out these tutorials:

Searching Documents with VQL

This tutorial covers how to use Vault’s query language (VQL) to search document fields and document content. VQL’s syntax is similar to SQL and provides a programmatic way of searching your vault’s data. Not all components are supported in VQL. See VQL documentation for a full listing.

Queryable Fields

To query a specific field or to use it in a WHERE clause filter statement, the field must be queryable. The component’s metadata API can tell you which fields are queryable.

Below we’ve made a call to the document field metadata API. The response shows ”queryable”: true for id. This means that id is queryable and you can use it in SELECT and WHERE clauses of your VQL statement.

Request

$ curl -X GET -H "Authorization: {SESSION_ID}" \ 
https://{server}/api/{version}/metadata/objects/documents/properties

Response

{
  "responseStatus": "SUCCESS",
  "properties": [
    {
      "name": "id",
      ...
      "queryable": true
    },
   
   ]
}

Sending Queries

VQL queries go to the /query REST interface. Let’s query the id and name__v fields of our documents to see how this works.

This request uses the name property of the document field (name__v), not the label (Name). Likewise, for the id field we use the name property, which in this case is the same as its label. You can get the name property via the metadata API.

Request

curl -X POST -H "Authorization: {session_id}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'q=select id, name__v from documents' \
"https://{server}/api/{version}/query"

Response

{
"responseStatus":"SUCCESS",
"responseDetails":{
"limit":1000,
"offset":0,
"size":1000,
"total":1647,
"next_page":"/api/v16.0/query/63f318d1-9f83-4073-b3bf-0b44d3c6c175?limit=1000&offset=1000"},
"data":[{"id":1000,"name__v":"file 2"},{"id":1001,"name__v":"file 2"},

Searching Document Versions

This section looks at some basic keyword searches on documents and explores the ALLVERSIONS and LATESTVERSION search options.

As a document moves through its lifecycle and versions, its source file and field values will change. By default, queries only include the latest version. Searching previous versions requires additional syntax.

Using the ALLVERSIONS and LATESTVERSION syntax, you could find:

The examples in this section use a document with the following versions:

Version State Keywords in Content Notes
0.1 Draft Insulin Added “Insulin”
0.2 Draft Insulin, Contraindications Added “Contraindications”
1.0 Approved Insulin, Dosage Removed “Contraindications”; Added “Dosage”; this is a past steady state version
1.1 Draft Insulin, Dosage No change
2.0 Approved Insulin, Prescribing Removed “Dosage”; Added “Prescribing”; this is the latest steady state version
2.1 Draft Insulin, Prescribing No change
2.2 Draft Insulin, Formulary Removed “Prescribing”; Added “Formulary”; this is the latest version

Query the Document by Name

First, we’ll query the document using the WHERE filter on the document name:

SELECT id, minor_version_number__v, major_version_number__v FROM documents WHERE name__v = 'WonderDrug Information'
{
    "responseStatus": "SUCCESS",
    "responseDetails": {
        "limit": 1000,
        "offset": 0,
        "size": 1,
        "total": 1
    },
    "data": [
        {
            "id": 534,
            "minor_version_number__v": 2,
            "major_version_number__v": 2
        }
    ]
}

This response returns the latest version of the document, version 2.2.

Find Keywords in Content

Next, we’ll use the FIND operator to search for documents with the keywords “Contraindications”, “Dosage”, or “Prescribing” in the document content. We have not specified a version option, so this search only includes the latest document versions. This query uses ‘SCOPE’: this indicates whether you want to search the full text of the document’s rendition ('content’), the document’s field values ('properties’), or both ('all’).

SELECT id, minor_version_number__v, major_version_number__v FROM documents FIND 'Contraindications OR Dosage OR Prescribing' SCOPE content
{
    "responseStatus": "SUCCESS",
    "responseDetails": {
        "find": "Contraindications OR Dosage",
        "limit": 1000,
        "offset": 0,
        "size": 0,
        "total": 0
    },
    "data": []
}

The query returns no results because “Contraindications” was removed from the document content when it changed from version 0.2 to 1.0, “Dosage” was removed when it changed from version 1.1 to 2.0, and “Prescribing” was removed when it changed from version 2.1 to 2.2. For most document searches, only the latest version is relevant, so this result is what you’d want to see.

Find Keywords Across Versions

Occasionally, you may want to include past versions in your document search. To do this, we’ll add ALLVERSIONS to the FROM clause.

SELECT id, minor_version_number__v, major_version_number__v FROM ALLVERSIONS documents FIND 'Dosage' SCOPE content
{
    "responseStatus": "SUCCESS",
    "responseDetails": {
        "find": "Dosage",
        "limit": 1000,
        "offset": 0,
        "size": 2,
        "total": 2
    },
    "data": [
        {
            "id": 534,
            "minor_version_number__v": 1,
            "major_version_number__v": 1
        },
        {
            "id": 534,
            "minor_version_number__v": 0,
            "major_version_number__v": 1
        }
    ]
}

The query found our keyword in versions 1.1 and 1.0. If we queried “Insulin” (present in all seven versions), the response would look similar to the one above, with a result for each document version.

Find the Latest Matching Version

Sometimes, you want to find only the latest version that meets your criteria. To do this, we place LATESTVERSION in the SELECT clause and (as above) ALLVERSIONS in the FROM clause:

SELECT LATESTVERSION id, minor_version_number__v, major_version_number__v FROM ALLVERSIONS documents FIND 'Dosage' SCOPE content
{
    "responseStatus": "SUCCESS",
    "responseDetails": {
        "find": "Dosage",
        "limit": 1000,
        "offset": 0,
        "size": 1,
        "total": 1
    },
    "data": [
        {
            "id": 534,
            "minor_version_number__v": 1,
            "major_version_number__v": 1
        }
    ]
}

This query found the latest version (1.1) in which our keyword exists. Contrast this with the previous result, which found our keyword in multiple versions. Using LATESTVERSION is most useful when the keyword exists in many different versions and you only want the latest.

Searching Document States

Searching document states another way to search across document versions. The following examples use the same document as the previous examples.

As of v9.0, document state parameters use the following format:

SELECT fields FROM documents WHERE status__v = steadystate()
SELECT fields FROM documents WHERE status__v = supersededstate()
SELECT fields FROM documents WHERE status__v = obsoletestate()

Search for Steady State Documents

This query searches all document versions for those with “Insulin” in the content, then filters to find the latest steady state version.

SELECT LATESTVERSION id, minor_version_number__v, major_version_number__v FROM ALLVERSIONS documents FIND 'Insulin' SCOPE content WHERE status__v = steadystate()
{
    "responseStatus": "SUCCESS",
    "responseDetails": {
        "find": "Insulin",
        "limit": 1000,
        "offset": 0,
        "size": 1,
        "total": 1
    },
    "data": [
        {
            "id": 534,
            "minor_version_number__v": 0,
            "major_version_number__v": 2
        }
    ]
}

The query found our keyword “Insulin” in version 2.0 of the document. The keyword exists in all versions of the document, including both steady state versions (1.0 and 2.0), but the query returned only 2.0 because of the LATESTVERSION syntax.

Other Keywords

If we performed the same query as above, substituting “Insulin” for:

Search for Superseded Documents

This query searches all document versions for those with “Insulin” in the content, then filters to find the latest superseded state version.

SELECT LATESTVERSION id, minor_version_number__v, major_version_number__v FROM ALLVERSIONS documents  FIND 'Insulin' SCOPE content WHERE status__v = supersededstate()
{
    "responseStatus": "SUCCESS",
    "responseDetails": {
        "find": "Insulin",
        "limit": 1000,
        "offset": 0,
        "size": 1,
        "total": 1
    },
    "data": [
        {
            "id": 534,
            "minor_version_number__v": 0,
            "major_version_number__v": 1
        }
    ]
}

The query found our keyword “Insulin” in version 1.0 of the document. Version 1.0 was the latest steady state version until it was superseded by version 2.0. We’d get the same result for the keyword “Dosage, but no result would be returned for any of the other keywords.

Search for Obsolete Documents

The examples above use a document that is actively progressing through Draft and Approved states. For the next example, the document has been retired from use and it has moved to Obsolete state. When this occurs, all versions of the document also become obsolete.

SELECT id, minor_version_number__v, major_version_number__v FROM ALLVERSIONS documents  FIND 'Insulin' SCOPE content WHERE status__v = obsoletestate()
{
    "responseStatus": "SUCCESS",
    "responseDetails": {
        "limit": 1000,
        "offset": 0,
        "size": 7,
        "total": 7
    },
    "data": [
        {
            "id": 534,
            "minor_version_number__v": 1,
            "major_version_number__v": 2
        },
        {
            "id": 534,
            "minor_version_number__v": 0,
            "major_version_number__v": 2
        },
        {
            "id": 534,
            "minor_version_number__v": 1,
            "major_version_number__v": 1
        },
        {
            "id": 534,
            "minor_version_number__v": 2,
            "major_version_number__v": 0
        },
        {
            "id": 534,
            "minor_version_number__v": 0,
            "major_version_number__v": 1
        },
        {
            "id": 534,
            "minor_version_number__v": 1,
            "major_version_number__v": 0
        },
        {
            "id": 534,
            "minor_version_number__v": 2,
            "major_version_number__v": 2
        }
    ]
}

This query returned all versions of the document. If we include FROM LATESTVERSION in the query string, this would return only version 2.2.

Find Document’s Current Status

Let’s query the same document to retrieve its current status:

SELECT id, name__v, status__v FROM documents WHERE id = 534
{
    "responseStatus": "SUCCESS",
    "responseDetails": {
        "limit": 1000,
        "offset": 0,
        "size": 1,
        "total": 1
    },
    "data": [
        {
            "id": 534,
            "name__v": "WonderDrug Information",
            "status__v": "Obsolete"
        }
    ]
}

Searching Archived Documents

Archiving is a way to hide old documents that are no longer relevant in day-to-day operations without removing them from your vault. Archiving a document archives all of its versions. Archived documents are excluded from search results by default, but you can choose to search your vault’s archive by adding archived_documents to the FROM clause.

Note: This functionality is available in v15.0 and later. Document archive is not available in all vaults. Learn more in Vault Help.

Find All Archived Documents

To find for all archived documents:

SELECT id, name__v FROM archived_documents

Find All Archived Documents

Like other document queries, searching archived documents defaults to LATESTVERSIONS. You add ALLVERSIONS to the FROM clause.

Next Steps

After finishing this tutorial, you can learn more about VQL in these articles:

Creating & Downloading Documents in Bulk

In this tutorial we’ll discover two ways of creating documents in batch: using Bulk Document Create API and using the Vault Loader Command Line Interface. We’ll also look at how to download documents in batch.

Note: This tutorial uses CSV for input and output, but these API requests could also accept JSON.

Vault Loader CLI

You can download Vault Loader CLI from the Vault UI, as shown below. Learn more about Vault Loader CLI in Vault Help

Vault Loader CLI Download

Document Creation Overview

Creating multiple documents is a two-step process. First, upload the source files to the staging server via FTP. Then, make the API call to set the metadata attributes (field values) of the documents. This API call also begins the process of copying files from the staging server to your vault.

Create Documents

In the API call, you must provide values for all required attributes, for each document that you’re creating. See Understanding Metadata to learn about retrieving the required attributes.

The request below creates three documents from source files doc1.txt, doc2.txt, and doc3.txt. The required metadata attributes for these documents are name__v, type__v and lifecycle__v.

The file column and suppressRendition are not required: * The file attribute tells Vault where to look for the source file on the FTP server. Omitting this column or leaving the value blank would create document placeholders. * The suppressRendition attribute tells Vault to delay generating a viewable rendition for the document until a user views the document from the UI. This setting reduces the load on your vault by preventing unnecessary processing.

CSV Input

Both of the requests below use the create_documents.csv input file.

file,name__v,type__v,lifecycle__v,suppressRendition
doc1.txt,doc1,type,eTMF Lifecycle,true
doc2.txt,doc2,type,eTMF Lifecycle,true
doc3.txt,doc3,type,eTMF Lifecycle,true

Request

Using curl:

curl -X POST -H "Authorization: {SESSION_ID}" \
-H "Content-Type: text/csv" \
-H "Accept: text/csv" \ 
--data-binary @"C:\Vault\Documents\create_documents.csv" \
https://myvault.veevavault.com/api/v15.0/objects/documents/batch

Using the command line interface:

java -jar VaultDataLoader.jar -createdocuments -csv create_documents.csv

Response

You can see from the response that all documents were successfully created. The id column returns the system ID generated for each document and row_id maps each row back to the original input.

responseStatus,id,name__v,type__v,lifecycle__v,errors,row_id
SUCCESS,1634,,,,,1
SUCCESS,1635,,,,,2
SUCCESS,1636,,,,,3

CLI Async Mode

You can run the CLI asynchronously and free up the command prompt. The CLI gives you a job ID that you can use to track the job status. When the job is complete, you can use -jobresults to download the results, which are similar to the CSV above. In async mode, these don’t download automatically.

Example: CLI Async

These examples show the same document creation process as above, but using the CLI in asynchronous mode:

>> java -jar VaultDataLoader.jar -createdocuments -csv createdoc.csv -async
Job 10479 submitted.

>> java -jar VaultDataLoader.jar -jobstatus 10479
ID         Type                      Status          Progress        Start Time      End Time        Expiration Date
10479      create-documents          Success         3 / 0           2016-11-28      2016-11-28      2016-12-14
                                                                     02:23:49AM GMT  02:23:53AM GMT  02:23:53AM GMT

>> java -jar VaultDataLoader.jar -jobresults 10479

Downloading Documents

Vault Loader (UI or CLI) provides the most efficient way to download source files and renditions. This section describes how to accomplish this from the CLI.

Download Location

Vault Loader downloads source files and renditions to the vault’s FTP staging server, not your local machine. Once the process is complete, you can download the files via FTP. The results output will indicate where the files reside on the server and which versions were included in the extract.

Vault uses the following directory structure for downloaded files: {job_id}/{doc_id}/{major_version_number_v}/{minor_versionnumber__v}/`

Download Limits

The FTP server automatically removes downloaded files after the job’s Expiration Date.

Vault Loader cannot extract more than 2,000 files (source files and renditions) in a single job.

Example: Downloading with CLI

>> java -jar VaultDataLoader.jar -exportdocument -source -where "id contains (1634, 1635, 1636)" -async

>> java -jar VaultDataLoader.jar -jobstatus 10381
ID         Type                      Status          Progress        Start Time      End Time        Expiration Date
10381      export-documents          Success         3 / 0           2016-11-28      2016-11-28      2016-12-14
                                                                     04:24:25AM GMT  04:24:25AM GMT  04:24:25AM GMT
>> java -jar VaultDataLoader.jar -jobresults 10381
file,id,external_id__v,rendition_type__v,major_version_number__v,minor_version_number__v
/10381/1636/0_1/doc3.txt,1636,,,0,1
/10381/1634/0_1/doc1.txt,1634,,,0,1
/10381/1635/0_1/doc2.txt,1635,,,0,1

Next Steps

Now that you know how to create and download documents, check out our tutorial on querying document metadata attributes using VQL.

API Rate Limits

API rate limits are a common way to guarantee a high quality service by preventing servers from becoming overloaded and the web service itself from becoming unusable. Web services are a fundamental resource to any developer application or integration. We enforce rate limits to ensure that each application or integration gets its fair share of this resource. Learn more about API rate limits in Vault Help.

What Are Rate Limits?

Rate limits constrain the number of API calls a user can make during a given time period. Once you reach your API quota, the server will reject your subsequent API requests until the next window.

How Does Vault Calculate Limits?

Vault enforces two types of rate limits:

When you exceed these limits, the server throws an API_LIMIT_EXCEEDED error. It is important to be able to handle this error, even if you’ve followed the API rate limit best practices discussed below.

API Rate Limit Headers

As of v14.0, Vault APIs return two rate limiting headers in every response to help you keep track of how many API calls you have remaining.

Rate Limit Header

The X-VaultAPI-BurstLimitRemaining header refers to the burst limit and indicates the number of API calls you have remaining for the current window. The X-VaultAPI-DailyLimitRemaining refers to the 24-hour rolling daily limit and indicates the number of API calls you have remaining in the current 24-hour window.

Developing with Rate Limits

Here are some best practices for reducing the number of API requests:

  1. Avoid unnecessary auth calls. A session ID stays alive as long it is active. A session ID with a timeout of 20 minutes only expires if it has not been used within the past 20 minutes.

  2. Cache configuration data. Configuration data does not change often. Retrieve it once and store it locally in a database like SQLite or serialized in a file.

  3. Optimize your code to eliminate unnecessary API requests. Are you retrieving data that isn’t being used in your application? Are you updating data that hasn’t changed? Eliminate these calls.

  4. Regulate the API request rate. If you are frequently approaching or reaching the API rate limit, consider implementing a throttling process in your application to distribute your requests more uniformly over time. For example, monitor your request rate and throttle requests when your rate reaches a certain threshold.

  5. Use the batch/bulk APIs. You can drastically reduce your API request count if you take advantage of the many batch/bulk APIs available. For example, a single API request can create 500 object records using the Batch Object Create API. Find opportunities to replace single API calls with their batch counterpart. Note: Batch APIs are not currently available on all resources.

Vault External Document Viewer

Overview

You can embed the external document viewer into a website or use it as a standalone viewer for documents in your vault. Vault ensures that only the latest steady state version of the document will be accessible through the viewer at all times.

Note: The external document viewer is only available in PromoMats and MedComms vaults with the Public Distribution and View-Based User license type features enabled. Learn more in Vault Help.

The External Viewer has the following unique properties:

The Token API generates document access tokens needed by the external viewer:

Setting up the External Viewer

You can include the following snippet of JavaScript code into your website to display a specific Vault document.

<!DOCTYPE html>
<html>
 <body>
   <!-- 1. The <iframe> (and vault viewer) will replace this <div> tag. -->
   <div id="viewer"></div>

   <script>
     // 2. This code loads the IFrame Viewer API code asynchronously.
     var tag = document.createElement('script');

     tag.src = "https:​//js.veevavault.com/vault.js";
     var firstScriptTag = document.getElementsByTagName('script')[0];
     firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

     // 3. This function creates an <iframe> (and vault viewer) after the API code downloads.
     var viewer;
     function onVeevaVaultIframeAPIReady() {
       viewer = new VV.Viewer('viewer', {
         height: '600',
         width: '600',
      error: 'We\'re sorry. The document you are trying to view is not available.'
       });
     }
   </script>
 </body>
</html>

Once the viewer is embedded, a Vault Document Token generated for the desired document needs to be provided in the URL parameters, as well as a DNS parameter to pass the source Vault’s DNS.

Generating Tokens for Vault Documents

Send POST to /api/{VERSION}/objects/documents/tokens

Headers

Input Content-Type - Name-Value Pair application/x-www-form-urlencoded
Response Accept - JSON application/json (default) or XML application/xml

Parameters

Document IDs

Required - Include the docIds request parameter with a comma-separated string of document id values. This will generate tokens for each document. For example: docIds=101,102,103,104

Token Expiration Date

Optional - Include the expiryDateOffset request parameter set to the number of days after which the tokens will expire and the documents will no longer be available in the viewer. If not specified, the tokens will expire after 10 years by default.

Download Option

Optional - Include the downloadOption request parameter set to PDF, source, both, or none. These allow users viewing the document to be able to download a PDF version or source version (Word, PPT, etc.) of the document. If not specified, the download options default to those set on each document.

Distribution Channel

Optional - Include the channel request parameter set to the website object record id value that corresponds to the distribution channel where the document is being made available.

Token Groups

Optional - Include the tokenGroup request parameter. This only required if you want to group together generated tokens for multiple documents in order to display the documents being referenced in the same viewer. This value accepts strings of alphanumeric characters (a-z, A-Z, 0-9, and single consecutive underscores) up to 255 characters in length.

The token that is passed as a URL parameter to the External Viewer is the primary token and the document it references will be displayed normally. However, any additional documents that have tokens generated with the same case-sensitive tokenGroup string will be displayed in a sidebar of the viewer.

The order of documents in the sidebar depends on the order in which the tokens are generated. If multiple tokens are generated with one request, the documents will be ordered top-to-bottom based on the order they are passed to the docIds parameter.

For example: If passing the parameters docIds=101,102,103,104 and tokenGroup=group_1 with the request, the top-to-bottom order in the sidebar will be documents 101, 102, 103, 104. If a new request is then made with the parameters docIds=105 and tokenGroup=group_1, document 105 will be added below document 104 in the previous list.

Example

$ curl -X POST -H "Authorization: {SESSION_ID}" \ 
-H "Content-Type: application/x-www-form-urlencoded" \
-d "docIds=101,102,103,104" \
-d "expiryDateOffset=90" \
-d "downloadOption=PDF" \
-d "channel=00W000000000301" \
https://myvault.veevavault.com/api/v12.0/objects/documents/tokens

Response

{
    "responseStatus": "SUCCESS",
    "tokens": [
        {
            "document_id__v": 101,
            "token__v": "3003-cb6e5c3b-4df9-411c-abc2-6e7ae120ede7"
        }
        {
            "document_id__v": 102,
            "token__v": "3003-1174154c-ac8e-4eb9-b453-2855de273bec"
        },
        {
            "document_id__v": 103,
            "token__v": "3003-51ca652c-36d9-425f-894f-fc2f42601fa9"
        },        
        {
            "document_id__v": 104,
            "errorType": "OPERATION_NOT_ALLOWED",
            "errors": [
                {
                    "type": "INVALID_DOCUMENT",
                    "message": "Document not found [104]."
                }
            ]
        }
    ]
}

Details

In the example above, tokens are generated for the first three documents. The fourth document could not be found. This indicates either an incorrect document id or that the specified document is a binder.

Errors

Error Type Error Message Comments
INSUFFICIENT_ACCESS User does not have sufficient privileges to perform the action. The logged-in API user does not have permission to complete the request.
OPERATION_NOT_ALLOWED Cannot create resource: [Approved Email] is not enabled. This error indicates that your vault has not been configured for use with the integration feature: “Approved Email” or “Public Distribution”. Learn more in Vault Help.
INVALID_DOCUMENT Document not found [{ID}] The document id specified in the request cannot be found in your vault. This error is also returned if the specified document is a binder (binder__v=true).
INVALID_DATA Invalid value [{VALUE}] specified for parameter [downloadOpt] specified: one of [None, PDF, Source, Both] is expected. If using the downloadOption request parameter to set the document download options, valid values are None, PDF, Source, or Both.
INVALID_DATA Invalid value [{VALUE}] specified for parameter [tokenGroup]: string exceeds max length [255]. The tokenGroup value cannot exceed 255 characters.
INVALID_DATA Invalid value [{VALUE}] specified for parameter [tokenGroup]: value can only contain [a-z, A-Z, 0-9, single consecutive ’_’]. The tokenGroup value has invalid character values.
INVALID_DATA Invalid value [{VALUE}] specified for parameter [channel]: valid [channel] is expected. If using the channel request parameter to associate the documents with a particular distribution channel, you must enter a valid website__v object record ID.

How to Create the URL

When sharing your documents in an embedded viewer, users must navigate to a URL that includes both the anonymous viewing token and your vault’s DNS:

https://{PAGE_WITH_EMBED_SCRIPT}?token={VIEWING_TOKEN}&dns={CUSTOMER}.veevavault.com`

For example, a URL for information for the CholeCap product might be:

https://cholecap.com/about.html?token=3003-cb6e5c3b-4df9-411c-abc2-6e7ae120ede7&dns=myvault.veevavault.com

If you want to display multiple documents in the viewer, use the tokenGroup parameter when requesting tokens and use any of the tokens from the response within the URL. Vault will determine whether a token belongs to a group and will automatically show all documents within the group. The token in the URL corresponds to the document that displays when the viewer loads.

Using the FTP Server

Each vault in your domain has its own FTP staging server. You can use this as a temporary storage area for files you’re loading. Vault also uses it to store extracted files. The URL of each staging server is the same as the corresponding vault. Before loading any input that references a file, you must upload the file to the server via FTP. These files can include source files and renditions for documents, or user images for user profiles.

Note: The staging server automatically removes files at regular intervals. Your staging server can hold any number of files, but only 64,998 can display.

How to Connect

Access a staging server using your favorite FTP client or through the command line. Use the following settings with an FTP client:

Note: The staging server does not support SAML SSO authentication.

Staging Server Permissions

Uploading to or downloading from the staging server requires a security profile with the FTP Staging > Access permission. Only the standard Vault Owner and System Admin profiles include this by default, but Admins can add this permission to other profiles.

Only Vault Owners and System Admins can upload files to the default FTP staging location. All other users can only upload files to their own user directory, which means they need to specify that file path when referring to those uploaded files. User directories are always in the format u{user_id}.

For example, Clara is not a Vault Owner or System Admin. She can only upload files directly to vault1234/u5678, where 1234 is the id of her vault and 5678 is her user_id. After uploading files, Clara specifies her document file parameters to /u5678/document.docx. Note that Clara can still make new directories inside of her user directory, such as /u5678/uploads/document.docx.

How to Use the Server for Inputs

To reference files:

How to Use the Server for Extracts