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.

Versioning

The only version of the Vault REST API subject to change is the newest version, labelled as Beta. The newest version of the API which is not subject to change is the General Availability version, labelled as GA. All older versions of the API (all versions besides Beta) do not change, which ensures your integration will continue to work. However, this means many new APIs and API features are not backwards compatible, and you will need to use a newer version of the API to access new functionality. To view the new APIs, features, and fixed issues for each API version, you can check the Release Notes.

Naming

Veeva Vault releases three new API versions each year, coinciding with Vault General Releases. As of 2017, REST API versions follow the pattern YY.1, YY.2, YY.3 where YY is the last two digits of the current year. For example, the first Vault General Release of 2017 is 17R1. The API version which coincides with this release is API v17.1. The third Vault General Release of 2018 is 18R3, which coincides with REST API v18.3.

Prior to 2017, Vault versions and API versions do not coincide with the current year. For example, REST API v12.0 includes features from Vault 11.5.2, 11.5.3, and 12.0.0, all of which released in 2015. Each General Release is made up of multiple limited releases. For example, Vault release 18R1 includes all features released in 17R3.2, 17R3.3, 17R3.4, and 17R3.5. The REST API versioning does not have limited release numbering. Instead, the latest version (in this example, v18.1) is labelled as Beta and all limited release features are added to the Beta API. For example, REST API v18.1 contains all features released in 17R3.2, 17R3.3, 17R3.4, and 17R3.5.

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:

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:

For example, a vault might allow 500 API requests within a 5-minute window. Between 4:00 and 4:03, your vault has received 500 requests. On request 501 at 4:04, the server rejects your request. The server will continue to reject requests until the next window begins at 4:05.

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. Note that the the Job Status endpoint will return this error if requested more than once in 10 seconds, which does not mean you’ve exceeded your burst or daily limits.

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.

As of v19.2, Vault APIs return two additional rate limit headers in every response showing the total limits allowed for your vault.

API calls to auth never return rate limit headers, but these calls still count towards your burst and daily limits.

Note that the Job Status endpoint will return the API_LIMIT_EXCEEDED error if requested more than once in 10 seconds, and these headers are not relevant when this happens.

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.

Client ID

For additional tracking purposes, every Vault REST API call will accept an optional client ID to represent an external integration client. You can provide this data via a query parameter called client_id, query parameter, or HTTP Header called X-VaultAPI-ClientID. If client ID is included as both a HTTP Header and query parameter, the HTTP Header is ignored.

The Vault API will record the client ID value for each API call. This ID appears in the API Usage Logs, which is downloadable through the UI and API. If an API request does not include a client ID, the value will appear as unknown in the API Usage Log. The API Usage Log is only available in v18.1+, but client ID can be included in requests for all versions of the API.

Format

A valid client ID must be an alphanumeric string with a maximum of 100 characters. A client ID can be mixed-case and the only special characters allowed are underscores _ and hyphens -. If an API request includes an invalid client ID, the value will appear as invalid_client_id in the API Usage Log.

To avoid clashing with other integrations or client applications running on Vault, we recommend that you format your client ID as follows:

{company}-{organization}-{component/team}-{server | client}-{program}

For example, the Vault Loader team client ID could be:

veeva-vault-tools-server-loader

Cross-Origin Requests

Cross-Origin Resource Sharing (CORS) and JSONP are currently unsupported. If you want to integrate your web application directly with the Vault API, you must route API requests through your own backend and not directly from the browser via AJAX.

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™, PowerPoint™, 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. If no website record is specified, Vault will assume the request is for Approved Email.

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.

Limitations: Vault does not support the ability for cross-domain users to login to FTP Servers on a cross-domain vault. This applies even to members of cross-domain vaults that can login via the UI.

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

Scalable FTP

As of 19R1.3 (May 31st 2019), the Scalable FTP feature will upgrade the Vault FTP infrastructure to make it more robust, scalable and future-proof, by taking a greater advantage of AWS™. This article outlines the details and value of the Scalable FTP enhancements and its impact on the Vault FTP infrastructure.

Note: This feature has changed the FTP date behavior in the FTP client so that the timestamp of all subdirectories will display the date of the root directory. For example, if uploading a folder on 12/1/18 and the FTP root directory was mounted on 6/1/2018, the FTP client shows the last modified date of 6/1/2018.

Overview

Prior to this upgrade, the FTP server along with its staging area resided on the same hardware as the rest of the vault. This created some challenges that we’ve addressed with the following updates:

Scalable FTP addresses these challenges and improves on a number of other areas.

Process and Document Artifact Creation

To understand the value of enhancements provided by the Scalable FTP, we’ll first review the typical process of migrating documents into Vault.

For users, this process simply involves uploading and creating documents. For managing migrations and implementations, the typical process consists of the following steps:

  1. FTP upload to a Sandbox or Test Vault environment.
  2. Author migration scripts, test, and validate document creation.
  3. Execute in a production Vault environment for final launch.

Step 1: FTP Upload

The upload phase allows users to upload files to their vault using an FTP application or an integration written to transfer files over FTP protocol. During this process, Vault places the files in a staging area making them available for processing and for creating documents or document artifacts such as versions, renditions or attachments.

Step 2: Document Creation

Vault processes each uploaded file and performs a number of asynchronous tasks including placing files in the correct locations on AWS S3, encryption, checksum, calculation, MIME-type determination, rendition generation, etc.

To create documents or document artifacts such as versions, renditions and attachments in Vault, the user calls one of Vault Batch APIs or uses Vault Loader. Vault will use the files previously uploaded via FTP. As part of the document creation process, some tasks also execute synchronously. Upon completion of the synchronous tasks the user either receives IDs for the created artifacts or an error if the source files couldn’t be located in FTP staging area.

Step 3: Finalization

For the documents to become fully usable and searchable, Vault must first complete the asynchronous tasks. In this final step, Vault indexes the document metadata and content, and finalizes the calculation of checksums and MIME-types.

Performance and Enhancements

Vault executes a series of tasks in the above steps with each having an impact on performance. Although these enhancements have increased the length of some of these individual tasks, other tasks perform better as a result.

Before Scalable FTP, Vault FTP placed files on to a local file system upon upload. The process of uploading the files onto AWS S3 and file encryption was left to the asynchronous part of processing the process which impacted its overall performance.

With Scalable FTP, the files will be uploaded on to a robust AWS S3 file system immediately. The direct bypass on to the S3 file system does take additional time and the initial step of transferring files will take longer. However, placing the files on to S3 right away expedites most subsequent steps or eliminates them completely which ultimately improves overall performance. For example, because AWS S3 provides a robust, secured and encrypted storage mechanism and eliminates the need of file pre-encryption. The files will still be encrypted at rest.

Checksum Calculation

With Scalable FTP, we’ve made the checksum calculation process asynchronous and moved it to the finalization step of the FTP process. When creating documents in bulk and uploading files to the FTP staging server, Vault no longer updates the Checksum field value immediately. Instead, Vault sets the checksum value to “pending” until the asynchronous finalization step completes. Users will see the “pending” value in the UI, when performing a query via the API or VQL, or when in the metadata when using the document export bulk action. This improves on overall performance and makes documents readily available in Vault much sooner.

MIME-Type Calculation

The final calculation and confirmation of the media type has also become an asynchronous process. Vault now initially determines the media type based on the file extension after uploading via FTP. This allows for an accurate calculation of over 90% of files uploaded. In the unlikely event where Vault cannot determine the media type based on the file extension during bulk document creation, Vault may assign an inaccurate media type. However, Vault quickly resolves this condition by providing a secondary recalculation for this subset of files. This change significantly increases the performance of bulk document creation.

Network Load Balancing

To improve on network traffic during this process, Scalable FTP will utilize Network Load Balancers. This helps provide a near zero downtime of our FTP infrastructure. This however may impact customers using the Java FTP client library as part of their integration. As a workaround we advise the impacted customers to set ftpsClient.setRemoteVerificationEnabled to true in their integration code.

FTP Staging Area Linking

Frequently during large migrations, it is necessary to re-link the FTP staging area from one vault to another. For example, after uploading the files into Sandbox for testing, the subsequent production migration can use the same files from the staging area. However, there was a limitation where linking was only allowed as long as both vaults were located on the same POD.

With Scalable FTP, Vault no longer utilizes the local POD file system as the staging area, but instead uses a highly scalable AWS S3. This enhancement allows the ability to easily link the staging area to vaults across PODs.

Long Filename

The file name length limit has been increased. Now file name length is limited to 255 bytes while the complete path including the file name is limited to 955 bytes.