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
}

A session ID stays alive for up to 48 hours as long as it is active, and expires if it has not been used for a vault’s Session Duration. A session ID with a timeout of 20 minutes only expires 20 minutes after the last request finishes executing. Learn more about Session Duration in Vault Help.

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 several 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 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 rate limiting headers to help you monitor how many API calls you have remaining as well as possible response throttling.

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

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.

Authentication API Rate Limit Headers

As of v20.1, calls to /api/{version}/auth return two rate limit headers in every response showing you the total limits allowed for your vault and how many /api/{version}/auth calls you have remaining. These calls also count towards your burst and daily limits.

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 for up to 48 hours as long as it is active. A session ID with a timeout of 20 minutes only expires if it is not used within 20 minutes after the last request finishes executing.

  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, observe the above mentioned response headers and monitor your request rate. 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 counterparts. 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 or HTTP Header called X-VaultAPI-ClientID. If client ID is included as both a HTTP Header and query parameter, the query parameter 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 periods ., 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

Authentication Defaulting

When authenticating to Vault through the API, Vault authenticates the user to the vault specified in the vault_domain_name. For example, https://{vault_domain_name}/api/{version}/auth.

You can also override this domain with the vaultDNS parameter, which instead generates a session for the domain specified in this parameter.

If vaultDNS is omitted, or if the vaultDNS is an invalid or inactive vault, Vault generates a session for vault_domain_name.

If this domain is also invalid or inactive, Vault executes logic to authenticate the user to their default vault. The default vault is calculated with the following steps:

  1. The default vault is the vault where the user last logged in.
  2. If the user has never logged in, or if the last logged-in vault is inactive, the default vault is the oldest active vault where that user is a member.
  3. If the user is not a member of any active vaults, the user receives an error message and cannot authenticate.

For example, Miyah is cross-domain user with access to the following vaults in her home domain:

  1. An inactive vault created in 2019, where she last logged in
  2. An inactive vault created in 2020
  3. An active vault created in 2018
  4. An active vault created in 2016

If Miyah executes an authentication call without the vaultDNS parameter, and the domain specified in vault_domain_name is vault #2, Vault authenticates Miyah to her default vault because vault #2 is inactive. To calculate the default vault, Vault first attempts to authenticate Miyah to vault #1, which is where she last logged in. However, this vault is inactive. Instead, Miyah is authenticated to vault #4, the vault created in 2016. This is the vault with the oldest creation date Miyah has access to.

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.

Sending Session IDs with Post Message

A technology called postMessage is a secure method of sending data. There are several Vault configurations which may send data using postMessage. For more information about postMessage, you can visit Mozilla’s documentation.

When the Post Session credentials via Post Message checkbox is selected in a custom web tab, Vault sends the user’s session ID using postMessage rather than as a URL parameter. Learn more about custom web tabs in Vault Help.

When the Post Session Credentials via Form Data with Key “Session.id” checkbox is selected when configuring an external URL call job, Vault sends the user’s session ID using postMessage. Learn more about configuring external URL jobs in Vault Help.

Whenever these options are selected, you must adjust your application to receive information from postMessage.

Step 1: Ready

Your web application must send a “ready” message to Vault on the window load of the custom web tab or external URL. Below is sample code making request to Vault using jQuery:

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">

 (function($, Cookies, URI) {
           //Listen for message event from Vault
          $(window).on('message', function(e) {
}
       //console.log("---------Send ready message-----------");
      var readyMessage = JSON.stringify({'message_id':'ready', 'data': {}});
      window.parent.postMessage(readyMessage, '*');
}(jQuery, Cookies, URI));
</script>

Step 2: Listen

The postMessage happens after the initial page load, so your web application must then “listen” for message events when the window loads in a custom web tab. Vault will return JSON data with session ID.

Below is sample code using jQuery, js-cookies and URI to process a session ID from Vault:

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.1.4/js.cookie.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/URI.js/1.7.2/URI.min.js"></script>
<script type="text/javascript">

(function($, Cookies, URI) {
           //Listen for message event from Vault
           $(window).on('message', function(e) {
               var message = JSON.parse(e.originalEvent.data);
               if (message['message_id'] == 'session_id') {
                     console.log("Got session_id message:
    "+message['data']['session_id']);
                                    //Do something with Session ID
                 }
                //console.log("---------Send ready message-----------");
                var readyMessage = JSON.stringify({'message_id':'ready', 'data': {}})
                window.parent.postMessage(readyMessage, '*');
  }(jQuery, Cookies, URI));
</script>

Example JSON output of session ID from Vault:

{"message_id":"session_id","data": {"session_id":"9DA3848FF39392020…."}}

Once you have a session_id, your web application can store it using cookies. You can also pass the data into a variable to call the Vault REST API.

Using the File Staging Server

Each vault in your domain has its own file 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 the maximum number displayed by FTP is 64,998. To display more files, use the File Staging API. See List Items at a Path in the Vault Rest API Reference for details.

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. In addition, while you can create folders on your FTP server, you cannot rename or move existing folders.

How to Connect via FTP

Access a staging server using your favorite FTP client or through the command line. For the best performance, we recommend FileZilla®.

Note: If you are experiencing issues uploading large files, increase the FTP client timeout setting to 180 seconds.

Use the following settings with an FTP client:

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

How to Connect via API

In versions 20.3+, you can use the Vault REST API to upload and manage files and folders on your vault’s file staging server. See File Staging in the Vault Rest API Reference for details.

Staging Server Permissions

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

About Paths

Paths to files and folders are different for Admin and non-Admin users. Non-Admin users can only see their own files and folders. Admin users can see all files and folders on their vault’s file staging server, including the root directory and individual user directories. User directories are always in the format u{user_id}. Admin users must include the full path from the staging server’s root directory, even for files and folders in their own user directory, while non-Admin users must include the full path from their user directory’s root. For example:

How to Use the Server for Inputs

To reference files:

Note that after creation, you cannot rename or move directories on your file staging server via FTP. To move or rename directories via API, see Update a File or Folder in the Vault Rest API Reference.

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: Beginning June 27, 2019 through the second week of August, we are rolling out changes to the FTP server functionality. Once the changes have been made for your vault, you will no longer be able to rename or move folders on the FTP server.

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 file staging 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 the file 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 & 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 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 file 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

Vault infrastructure utilizes Network Load Balancers to improve network traffic and provide near zero downtime. The balancers, however, may adversely impact some FTP client applications and network proxies because the control connection IP addresses differ from those used for data connections. This difference may cause some FTP clients and proxies to experience connection errors. To mitigate these errors, we recommend setting Remove Verification to false in affected FTP client applications and proxies. For example, Java-based clients and integrations need to set ftpsClient.setRemoteVerificationEnabled to false. If this change is not possible, please contact Veeva Support.

File Staging Area Linking

Frequently during large migrations, it is necessary to re-link the file 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.

Safety Suite

Safety.AI Intake JSON Syntax

Format JSON files properly to maximize the amount of data Safety.AI can extract during intake.

Click the button below to download a sample JSON intake file.

Download Sample JSON

The following list describes the basic components of a Safety.AI JSON intake file:

Objects

When formatting JSON, each Safety.AI object section can contain unstructured and structured data. Structured data must be nested within the appropriate Safety.AI object.

Safety.AI supports the following standard objects:

Structured Data

For each object, Safety.AI can extract structured data from key-value pairs. Each JSON key must match a vault field, which can be either a standard or custom field. Structured fields must be nested under the structured parameter and within the appropriate Safety.AI object.

The following sections outline the key-value pairs for each standard field that Safety.AI can extract. In each object-type field, the value must exactly match the API Name for the vault object record.

case_product__v

The following structured key-value pairs can be nested under case_product__v:

Key Value Field Type Limits
rank__v Number Number 1-100 No decimal places
drug_role__v Name of the drug role Controlled Vocabulary record exactly as it appears in your vault Object (Controlled Vocabulary) -
product_reported__v Text string Text 250 characters
country_obtained__v 2 or 3-character abbreviation or full country name exactly as it appears in your vault Object (Country) -
case_product_dosage__v

You must nest case_product_dosage__v under case_product__v. The following structured key-value pairs can be nested under case_product_dosage__v:

Key Value Field Type Limits
batchlot_number__v Text string Text 35 characters
dose_number__v Number Number 0-2,147,483,647 up to 4 decimal places
dose_unit__v Name of the unit of measurement exactly as it appears in vault Object (Unit of Measurement) -
duration_number__v Number Number 1-99,999 up to 3 decimal places
duration_unit__v Name of the unit of measurement exactly as it appears in vault Object (Unit of Measurement) -
firstadmin_idate__v Date in the following format: yyyy-MM-dd'T'HH:mm:ss.SSSXXX. Imprecise dates are accepted and the minimum level of precision required is the year, yyyy. For example, 2012-02-26T03:45:12.123+03:30. Text 29 characters
lastadmin_idate__v Date in the following format: yyyy-MM-dd'T'HH:mm:ss.SSSXXX. Imprecise dates are accepted and the minimum level of precision required is the year, yyyy. For example, 2012-02-26T03:45:12.123+03:30. Text 29 characters
frequency_number__v Number Number 0-9,999 up to 8 decimal places
frequency_unit__v Name of the unit of measurement exactly as it appears in vault Object (Unit of Measurement) -
patient_adminroute_text__v Text string Text 60 characters
case_product_indication__v

You must nest case_product_indication__v under case_product__v. Note that currently you can add only one indication per case product. The following structured key-value pair can be nested under case_product_indication__v:

Key Value Field Type Limits
name_reported__v Text string Text 250 characters
case_adverse_event__v

The following structured key-value pairs can be nested under case_adverse_event__v:

Key Value Field Type Limits
rank__v Number Number 1-100 with no decimal places
event_reported__v Text string Text 250 characters
event_country__v 2 or 3-character abbreviation or country name exactly as it appears in your vault Object (Country) -
seriousness__v Comma-separated list of picklist values, exactly as they appear in your vault. For example, life_threatening_v or caused_prolonged_hospitalisation__v Picklist -
onset_idate__v Date in the following format: yyyy-MM-dd'T'HH:mm:ss.SSSXXX. Imprecise dates are accepted and the minimum level of precision required is the year, yyyy. For example, 2012-02-26T03:45:12.123+03:30. Text 29 characters
resolved_idate__v Date in the following format: yyyy-MM-dd'T'HH:mm:ss.SSSXXX. Imprecise dates are accepted and the minimum level of precision required is the year, yyyy. For example, 2012-02-26T03:45:12.123+03:30. Text 29 characters
outcome__v Name of the outcome Controlled Vocabulary record exactly as it appears in your vault Object (Controlled Vocabulary) -
case_contact__v

The following structured key-value pairs can be nested under case_contact__v:

Key Value Field Type Limits
rank__v Number Number 1-100 with no decimal places
qualification__v Name of the qualification Controlled Vocabulary record exactly as it appears in your vault Object (Controlled Vocabulary) -
title_value__v Text string Text 50 characters
firstname_value__v Text string Text 60 characters
middlename_value__v Text string Text 60 characters
lastname_value__v Text string Text 60 characters
organization_value__v Text string Text 60 characters
department_value__v Text string Text 60 characters
telephone_value__v Text string Text 33 characters
fax__v Text string Text 33 characters
email_address__v Text string Text 50 characters
email_consent__v true or false Boolean -
street_value__v Text string Text 100 characters
city_value__v Text string Text 35 characters
state_province_value__v Text string Text 40 characters
country_value__v 2 or 3-letter abbreviation or country name exactly as it appears in your vault Object (Country) -
postalcode_value__v Text string Text 15 characters
reporter_language__v The 2 or 3-letter ISO code for the reporter’s language, or the language name exactly as it appears in your vault Text Object (Language (ISO))
patient

The following structured key-value pairs can be nested under patient:

Key Value Field Type Limits
patient_id_value__v Text string Text 60 characters
gender_value__v Name of the gender Controlled Vocabulary record exactly as it appears in your vault Object (Controlled Vocabulary) -
height_value__v Number Number 0-350 with up to 3 decimal places
height_unit__v Name of the unit of measurement exactly as it appears in your vault Object (Unit of Measurement) -
dob_idate__v Date in the following format: yyyy-MM-dd'T'HH:mm:ss.SSSXXX. Imprecise dates are accepted and the minimum level of precision required is the year, yyyy. For example, 2012-02-26T03:45:12.123+03:30. Text 29 characters
age_unit__v Name of the age unit Controlled Vocabulary record exactly as it appears in your vault Object (Controlled Vocabulary) -
age_value__v Number Number 0-50000 with no decimal places
age_group__v Name of the age group Controlled Vocabulary record exactly as it appears in your vault Object (Controlled Vocabulary) -
dod_idate__v Date in the following format: yyyy-MM-dd'T'HH:mm:ss.SSSXXX. Imprecise dates are accepted and the minimum level of precision required is the year, yyyy. For example, 2012-02-26T03:45:12.123+03:30. Text 29 characters
autopsy_value__v Boolean (true or false) (Yes/No) -
detail

The following structured key-value pairs can be nested under detail:

Key Value Field Type Limits
receiptdate_idate__v Date in the following format: yyyy-MM-dd'T'HH:mm:ss.SSSXXX. Imprecise dates are accepted and the minimum level of precision required is the year, yyyy. For example, 2012-02-26T03:45:12.123+03:30. Text 29 characters
report_type__v Name of the report type Controlled Vocabulary record exactly as it appears in your vault Object (Controlled Vocabulary) -
Additional Fields

The Safety.AI Intake endpoint can ingest custom fields. If your vault is licensed for the Vault Safety Suite, including both Safety.AI and Safety, the JSON Intake endpoint can also ingest fields that are present on the Case and Case child objects but not on the Inbox Item object.

Consider the following requirements when formatting custom fields or Safety Case fields for JSON intake:

JSON Limits and Restrictions

Safety.AI imposes the following default limits on intake JSON files for each API call:

Download Additional Fields Limits and Restrictions