This is a REST API to the Approval Studio, design review, and packaging approval SAAS.
API utilizes its flow, authorization, storage, and so on.
Approval Studio basic concepts
From the business point of view, Approval Studio is based on a multitenant concept when a single user may be a part of one or more tenants (called Companies). Please see https://approvalstudio.freshdesk.com/ for detailed instructions on how to work with Approval Studio.
Currently the only point where you may choose a tenant is project creation, please see POST /api/v1/project / Request.
REST HTTP Codes
API may return one of the following HTTP codes:
HTTP Code
Response
200
Success. See the method description to get what and how the method returns.
400
Validation error. API validates input parameters and when finds an invalid parameter, throws HTTP code 400. Those errors are related to parameters’ presence, format, emptiness, etc. Validating against a database, like looking for data by an ID is conducted separately and reflected in case of error, in HTTP codes 404, 406, 412, etc., please see the method’s description for detailed explanations.
{
"errors": {
"parameterName": [
"'parameterName' must not be empty."
]
},
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|a4a45224-4a7c03bbd5172369."
}
HTTP Code
Response
404, 406, 412
Resource not found. Generally, it means that requested resources are either not found or somehow restricted to proceed. For example, if a given project id is non-existent, the project is not found so gets HTTP code 404.
429
Rate Limit Reached. API host calculates the number of calls per sec, minute, and hour, and when the rate of requests reaches the limit, throws HTTP code 429, which means that the API host is overloaded and the client needs to wait before retrying.
If the request gets blocked then the client receives a text response like this:
Status Code: 429
Retry-After: 58
Content: API calls quota exceeded! maximum admitted 2 per 1m.
Retry-After header value is expressed in seconds. And X-Rate-Limit-XXX HTTP headers are injected in the response:
X-Rate-Limit-Limit: the rate limit period (eg. 1m, 12h, 1d)
X-Rate-Limit-Remaining: number of requests remaining
X-Rate-Limit-Reset: UTC date-time (ISO 8601) when the limits reset
HTTP Code
Response
500
Infrastructure failure. This means critical unrecoverable technical error generally related to database connections, external services availability, hardware failure, etc. Depending on the client application flow you can retry the calling method or halt processing and call our technical support.
Authorization/authentication
The API is based on an authorization token which should be requested prior to using any available API methods.
The flow is the following: request auth token by calling POST/api/v1/token/login (see) providing Approval Studio’s username/password. If ok, the method returns an authorization token that you should provide with any other API call as an HTTP header like this: Authorization: Bearer XXXXXXXXXXX.
The token is valid for a limited amount of time, 600 minutes by default. When the token is expired and still used you will have the response HTTP code 401, Unauthorized :
If so, you need to obtain a new token.
If the token is invalid or not provided, it gets the same response HTTP code 401.
Token management
POST /api/v1/token/login
Authorizes a user. When successfully authorized is returns an authorization token which must be supplied to every API as a header, like "Authorization: Bearer YYYYYYYYYYYYYYYYY...".
keepAliveTime is an optional parameter that defines how much time the token will be valid. Response’s expirationDate provides an exact time of the token expiration (see below). Note: When keepAliveTime is zero, the default value is used (600 min/10 hours).
Error: The user uses Lite payment plan option. API is available only for Pro users. Please consult our support on this: https://approval.studio/contact/
GET /api/v1/token/validate
Validates an auth token. This method is an kind of a health checker, that validates an authentication token, if it’s still valid. You may use it to ensure that the your authentication process completed successfully or that the token is still valid in case of a long-running scenarious like external workflow engines where tokens are saved for further use.
Business project or product name this Approval Studio project related for, max-length 50 chars, optional.
design
Point to which type of design this is, max-length 50 chars, optional.
revision
Ideally, a sequential number or version number; generally a free form string max-length 50 chars, optional.
description
Any kind of additional information, descriptions, comment etc., max-length 200 chars, optional.
tags
Array of free-form single-word tags associated with the project, optional, max 20 elements of 20-chars tags.
dueDate
Optional date, UTC, that points to when the project is desired to be completed.
reviewStatus
r/o
pendingCount - count of non-completed review tasks assigned on the project
approvedCount - count of approves made on the project’s assets
rejectedCount - count of rejected made on the project’s assets
created
r/o
Refers to when the project was created, UTC.
templateUID
It is a new concept, introduced in API v.1.15. Project template is a set of some data, usually a JSON, that administrator can provide when creating a new project. That could be a list of users, emails, etc any other business-specific attributes that could be used in building a business flow and should be specific for every project. For example, you might need to create a review task just after the project creation and you use API to implement this. In that case, you may provide UID of a user to create a review task for. The template itself doesn’t make any changes in the default application flow, it’s just a customizable attribute.
kanbanColumnUID
It is an unique ID of the Kanban column this project is placed to on the dashboard.
folderUID
It is an unique ID of the folder this project is placed to on the dashboard.
Note: Kanban columns and folders are ways to group projects based on some your business needs, probably, based on a kind of state or position on flow. This is out of scope of this document.
Method/Path
Description
GET /api/v1/project
Gets a list of projects.
POST /api/v1/project
Creates new project.
PUT /api/v1/project
Edits existing project.
DELETE /api/v1/project
Deletes a project.
GET /api/v1/project/proofreport
Gets a link to a proof report for a project.
PUT /api/v1/project/state
Changes project’s state.
GET /api/v1/project
Returns one or more projects and projects’ assets, tasks, and reference documents – depending on the parameters passed.
All the parameters are optional; the method always uses AND combination of all the parameters.
Parameter
Type & Explanation
ProjectUID
string Unique project GUID. If provided, only one project will be retrieved.
Note: behavior is changed in v.1.15. Now if ProjectUID is provided and this project belongs to an appropriate client, you will get project data regardless of the owner list and whether you are an admin or not. In other words, if this project belongs to your client (tenant), you will get it.
States
string One or more project states, comma-separated, see ProjectStates above. Default value is Active,OnHold,Completed.
Query
string A free-form text to case-sensitive search in projects’ attributes: Project name, Customer, Project, Design, Revision, Description, Tags.
IsLoadAssets
boolean, false by default. If it is set, returns assets for every project as a child collection.
IsLoadLastVerAssets
boolean, true by default. If set, only the most recent version of every asset be returned. Ignored, if IsLoadAssets is not set.
IsLoadTasks
boolean, false by default. If set, a list of active tasks for every project would be returned as a child collection.
IsLoadRefDocs
boolean, false by default. If set, a list of uploaded reference documents for every project would be returned as a child collection.
IsLoadMetadata
boolean, false by default. If set, metadata for every project would be returned as a list of key-value entries.
string array Optional tag list, max 20 tags of max length of 25 chars each.
dueDate
ISO date Optional UTC date (or date-time) that point to a date when project supposed to be completed. The date affects the project’s status and sort order on the application dashboard.
projectOwnersUIDS
string array Mandatory list of the project owner(s)'s UIDs. At least one owner must be provided, max number of owners is 20.
{
"clientUID": "string", // Optional tenant(client) ID.
"projectName": "string", // Project name, mandatory.
"customer": "string",
"project": "string",
"design": "string",
"revision": "string",
"description": "string",
"tags": [
"string", "string"
],
"dueDate": "2020-12-07T20:56:38.818Z",
"projectOwnersUIDS": [ // Project owner(s), at least one owner must be provided.
"XXXXXXXX"
],
"templateUID": "string" // Optional project template UID. See client list to get an appropriate template UID.
"folderUID": "string" // Optional folder UID. See client list to get an appropriate folder UID.
}
Error: Project with the given ID not found or it has been already deleted.
Error: Folder with the given UID not available for this project.
Error: Project owner with the UID [XXXXXXXXXX] not available.
{
"version": "1.0",
"statusCode": 404,
"message": "Project not found or already deleted."
}
HTTP Code
Response
406
Error: Project editing is possible only when the project is Active or OnHold. Completed, Archived or InTransit projects are not mutable. Please see PUT /api/v1/project/state.
Error: Project with the given ID not found, and, therefore project deletion failed.
{
"version": "1.0",
"statusCode": 404,
"message": "Project not found."
}
HTTP Code
Response
412
Error: Project must be either Completed or Archived to be deleted.
GET /api/v1/project/proofreport
Returns URL to get a printable proof report for the given project. The method does not allow direct downloading.
Read result/downloadURL and navigate it to get the report body. The report is a plain single-layer PDF 1.4 file.
Request
The request is a set of URL GET parameters separated by &:
Error: Project with the given ID not found and therefore proof report generation failed.
{
"version": "1.0",
"statusCode": 404,
"message": "Project not found."
}
PUT /api/v1/project/state
Changes project’s state according to the state rules:
The diagram above explains the pre-requisite check for changing the project’s state. Note: The diagram above is a recommended way to change project’s state, it is not mandatory to follow it, but highly recommended. Note: Detailed description of the project management is out of scope of this document.
States
Those are the states:
State
Explanation
Active
Work on a project is undergoing. This is where all the review work is going on.
OnHold
Due to some reason you want to postpone working on a project. Setting state to OnHold moves the project to a separate lane. Tasks are still intact, the only difference from Active is a position on a separate lane on the dashboard.
Completed
When setting the state to Completed all project tasks are deleted and the project itself moves from the dashboard to a separate screen where all completes are stored separately. All the assets and reference documents are preserved as well as history etc. The project goes read-only.
Archived
This is generally the same as Completed but assets and reference documents are moved to a remote, slow storage. The process of moving files to other storage could take a while, so when it is going on, the system marks a project as InTransit (see below).
InTransit
Project is locked to InTransit state by API itself when it is switching to Archive state or, vice versa, from Archived to Active. You can’t set this state forcedly.
Error: Project with the given ID not found or it has been already deleted.
{
"version": "1.0",
"statusCode": 404,
"message": "Project not found."
}
HTTP Code
Response
406
Error: The project with the given ID already has the requested state; no updating made.
{
"version": "1.0",
"statusCode": 412,
"message": "Project already has state XXXX."
}
GET /api/v1/project/meta
This methods gets a key-value list of the metadata for the given project.
The concept of project’s metadata is the following: you can assign any kind of textual invisible for end-users data to a chosen project. Technically this is a list of key-value pairs.
Project’s metadata might be used to provide data necessary for integration with other software, like order number, linked with a project, email of contact person etc.
Note: Apart from this method, you may use GET /api/v1/project with flag IsLoadMetadata set to true. Curl:
This methods moves a given project to a given kanban column on the dashboard. Curl:
curl -X 'POST' \
'https://api.approval.studio/api/v1/project/kanban/column' \
-H 'accept: text/plain' \
-H 'Content-Type: application/json-patch+json' \
-d '{
"projectUID": "XXXXXXXXXX", // ProjectUID as is throughout the system.
"kanbanColumnUID": "asdFxQ" // A valid kanban column UID.
}'
Note: You may retrieve a list of Kanban column UIDs from the GET /api/v1/users method.
HTTP Code
Response
400
Error: Parameters’ validation failed.
See HTTP code 400 description.
404
Error: Project with the given UID not found.
404
Error: Kanban column with the given UID not available for this project.
Please read kanban column UIDs using the GET /api/v1/users method
406
Error: Can’t edit completed or archived projects.
You may move a project to a given kanban column only when this project is active or on hold.
POST /api/v1/project/folder
This methods moves a given project to a given folder on the dashboard. Curl:
curl -X 'POST' \
'https://api.approval.studio/api/v1/project/folder' \
-H 'accept: text/plain' \
-H 'Content-Type: application/json-patch+json' \
-d '{
"projectUID": "XXXXXXXXXX", // ProjectUID as is throughout the system.
"folderUID": "49lu" // A valid folder UID.
}'
Note: You may retrieve a list of folder UIDs from the GET /api/v1/users method.
HTTP Code
Response
400
Error: Parameters’ validation failed.
See HTTP code 400 description.
404
Error: Project with the given UID not found.
404
Error: Kanban column with the given UID not available for this project.
Please read kanban column UIDs using the GET /api/v1/users method
406
Error: Can’t edit completed or archived projects.
You may move a project to a given folder only when this project is active or on hold.
Asset management
Method/Path
Description
GET /api/v1/assets
Gets an asset instance.
DELETE /api/v1/assets
Deletes an asset.
POST /api/v1/assets/upload
Uploads an asset from file.
POST /api/v1/assets/upload_url
Uploads an asset from the Internet.
GET /api/v1/assets/download
Downloads an asset.
GET /api/v1/assets/proofreport
Gets a link to a proof report for an asset.
GET /api/v1/asset
Gets an asset instance by a given asset id.
Parameter
Type & Explanation
AssetUID
string Unique asset GUID.
Curl:
curl -X GET "http://api.approval.studio/api/v1/asset?AssetUID=XXXXXXX" -H "accept: text/plain"
Responses
HTTP Code
Response
200
Success. Asset instance returned.
"version": "1.0",
"statusCode": 200,
"message": "GET Request successful.",
"result": {
"assetUID": "xxxxxxxxxx",
"version": 1,
"name": "drawing.pdf",
"status": "Processed",
"reviewStatus": { // Proof review status (see proofing flow explanations).
"pendingCount": 1, // The asset has 1 uncompleted review task
"approvedCount": 2, // The asset has been approved 2 times
"rejectedCount": 3 // The asset has been rejected 3 times
},
"pagesCount": 3,
"created": "2020-10-22T08:09:05.778512",
"fileSize": 1063800,
"reviewUrl": "https://app.approval.studio/xxx", // URL to launch prooftool to view this asset.
"thumbnailUrl": "https://app.approval.studio/yyy" // URL to asset's thumbnail image (.jpg).
"fullSizeBitmapUrl": "https://app.approval.studio/zzz/pageNum" // URL to converted asset's image (.png).
}
}
Note: fullSizeBitmapUrl is provided in form "https://baseurl/assettoken/0" .
– “0” here is a zero-based page number, zero is used by default, but you can change it to whatever you need.
Please remember that some image asset formats are multipage (.pdf, .tiff, office formats etc.).
– You will get http code 404 if provide wrong page number, bigger than asset’s page count or if you provide negative value.
HTTP Code
Response
400
Error: Parameters’ validation failed.
See HTTP code 400 description.
HTTP Code
Response
404
Error: Asset with the given ID not found.
{
"version": "1.0",
"statusCode": 404,
"message": "Asset not found."
}
DELETE /api/v1/asset
Deletes an asset by a given asset id.
Asset deletion is an unrecoverable operation that leads to removing the asset from the project and deleting a file from storage.
It is no way to restore an asset after it has been deleted.
{
"version": "1.0",
"statusCode": 404,
"message": "Asset not found."
}
POST /api/v1/asset/upload
Uploads an asset and initiates asset processing.
It validates initial input and adds the asset to the asset processing queue, which runs asynchronously. After uploading you need to pool asset status to get to know when it is processed or failed to process.
You can upload assets directly to a selected project or point an upload task as an upload initiator.
Time required to process assets is highly dependent on asset file size, dimensions, number of pages, and on how much processing node(s) are loaded.
Asset processing may fail or be rejected due to a number of reasons, business and technical. Those could be asset type (file extension), resolution or physical size (in case of vector images - PDF/AI, etc), payment plan, and a number of other options. Please refer to the company’s site or/and support to learn more.
Request
Parameter
Type & Explanation
ProjectUID
string Unique project ID, mandatory.
FileName
form file Asset file name, mandatory. Note: It’s just a name, not a path.
Success. "Asset uploaded successfully and is pending to process.
{
"version": "1.0",
"statusCode": 200,
"message": "Asset uploaded successfully and is pending to process.
Track its status to catch when it is ready to use.",
"result": {
"assetUID": "AAAAAAAAAAAAAAAAA" // newly generated asset id.
}
}
HTTP Code
Response
400
Error: Parameters’ validation failed.
See HTTP code 400 description.
403
Error: You have reached the storage limit for your plan (XXX Gb) and therefore not allowed to upload new assets.
This code means you have no free storage space to upload a new asset; asset is not uploaded and will not be processed any further. Please buy more storage or contact support to assist in dealing with this.
404
Error: Project UID is either invalid or points to a non-existing or inactive project.
404
Error: Task UID is either invalid or points to a non-existing or inactive task.
{
"version": "1.0",
"statusCode": 404,
"message": "Project UID provided is either invalid or points to a non-existing or inactive project." -or-
"Task UID provided is either invalid or points to a non-existing or inactive task."
}
HTTP Code
Response
412
Error: Only task types UploadAssets and UploadChangedAsset are allowed.
412
Error: In case when it is UploadChangedAsset task: the file to upload must be the same type as the original file.
Note: UploadChangedAsset means that the project owner(s) requested a new version of the asset to upload. It is mandatory that all asset versions must be the same type, i.e. all versions of the same asset are PDF or JPEG or PNG, etc. If you provide a different file type, you get this error.
{
"version": "1.0",
"statusCode": 412,
"message": "Only task types UploadAssets and UploadChangedAsset are allowed." -or-
"File to upload must be the same type as the original file (.pdf)."
}
POST /api/v1/asset/upload_url
This method works, generally, in the same way as /api/v1/asset/upload with the only difference that the file to upload is taken from the publicly accessible http(s) server.
A mandatory URL parameter points to the file to upload and process as a project’s asset.
Request
Parameter
Type & Explanation
ProjectUID
string Unique project ID, mandatory.
FileName
form file Asset file name, optional. Note: It’s just a name, not a path. If not provided, the filename would be assigned automatically using filename taken form http header Content-Disposition. If this header is not provided, filename would be "asset.extension" where extension is taken from http content type.
Success. "Asset uploaded successfully and is pending to process.
{"version":"1.0","statusCode":200,"message":"Asset uploaded successfully and is pending to process. Track it's status to catch when it'd ready to use.","result":{"assetUID":"XXXXXXXXX"}}
HTTP Code
Response
400
Error: Parameters’ validation failed.
See HTTP code 400 description.
403
Error: You have reached the storage limit for your plan (XXX Gb) and therefore not allowed to upload new assets.
This code means you have no free storage space to upload a new asset; asset is not uploaded and will not be processed any further. Please buy more storage or contact support to assist in dealing with this.
404
Error: Project UID is either invalid or points to a non-existing or inactive project.
{
"version": "1.0",
"statusCode": 404,
"message": "Project UID provided is either invalid or points to a non-existing or inactive project."
}
Success. "Asset uploaded successfully and is pending to process.
{
"version": "1.0",
"statusCode": 200,
"message": "Document uploaded successfully and is pending to process.
Track its status to catch when it is ready to use.",
"result": {
"refDocUID": "AAAAAAAAAAAAAAAAA" // newly generated document id.
}
}
HTTP Code
Response
400
Error: Parameters’ validation failed.
See HTTP code 400 description.
HTTP Code
Response
404
Error: Project UID is either invalid or points to a non-existing or inactive project.
{
"version": "1.0",
"statusCode": 404,
"message": "Project UID provided is either invalid or points to a non-existing or inactive project."
}
POST /api/v1/refdoc/upload_url
This method uploads reference document by taking it from the publicly accessible http(s) server.
A mandatory URL parameter points to the file to upload and process as a project’s asset.
Request
Parameter
Type & Explanation
ProjectUID
string Unique project ID, mandatory.
FileName
form file Document file name, optional. Note: It’s just a name, not a path. If not provided, the filename would be assigned automatically using filename taken form http header Content-Disposition. If this header is not provided, filename would be "asset.extension" where extension is taken from http content type.
Success. "Document uploaded successfully and is pending to process.
{"version":"1.0","statusCode":200,"message":"Document uploaded successfully and is pending to process. Track it's status to catch when it'd ready to use.","result":{"refDocUID":"XXXXXXXXX"}}
HTTP Code
Response
400
Error: Parameters’ validation failed.
See HTTP code 400 description.
HTTP Code
Response
404
Error: Project UID is either invalid or points to a non-existing or inactive project.
{
"version": "1.0",
"statusCode": 404,
"message": "Project UID provided is either invalid or points to a non-existing or inactive project."
}
POST /api/v1/refdoc/add_url
Plain text URL is a kind of a reference document in the Approval Studio. You can either upload a file or add a URL to the list of reference documents in a project.
This method adds a URL to the document list for a given project.
Error: Reference document UID is either invalid or points to a non-existing or deleted document.
{
"version": "1.0",
"statusCode": 404,
"message": "Reference document not found or it was already deleted."
}
Task management
Method/Path
Description
GET /api/v1/task/all
Gets a list of tasks assigned to the user.
GET /api/v1/task
Gets a task instance.
DELETE /api/v1/task
Deletes an task.
POST /api/v1/task/asset_upload
Creates a new AssetUpload task.
POST /api/v1/task/refdoc_upload
Creates a new RefDocUpload task.
POST /api/v1/task/review_asset
Creates a new CreateReviewAsset task.
PUT /api/v1/task/complete
Completes a task.
GET /api/v1/task/all
Gets a list of tasks optionally filtered by task types, assigned to a currently logged-in user.
This is what a user sees in Approval Studio web application in the list of tasks in the dashboard.
Parameter
Type & Explanation
Types
string One or more task types, comma-separated.
Default value is UploadAssets, UploadRefDocs, ReviewAssets, ExternalReviewAssets, UploadChangedAsset, UploadVideo, ExternalReviewVideo, ReviewVideo.
If no parameter is provided or it is empty, a default list of types is used (see above).
Error: You cannot create a task for a project in the state Complete. Only projects that are Active or OnHold can have tasks.
412
Error: User with UID [ZZZZZZZZZZZZZ] not found.
{
"version": "1.0",
"statusCode": 412,
"message": "You cannot create a task for a project in the state [Complete]."
}
POST /api/v1/task/review_asset
Creates a new Review Asset Task for a given user, project, and a list of assets providing optional due date and comment.
Request
{
"projectUID": "XXXXXXXXXXXXXX", // Project this task belongs to, mandatory.
"userUID": "ZZZZZZZZZZZZZ", // User this task assign to, mandatory.
"assetUIDs": [
"AAAAAAAAAAAAAAAA1", // One or more assets to review, namdatory.
"AAAAAAAAAAAAAAAA2"
],
"dueDate": "2020-12-04", // Task due date, UTC, optional.
"comment": "comment text" // Comment text, optional.
}
Error: You cannot create a task for a project in the state [Complete]. Only projects that are Active or OnHold can have tasks.
412
Error: User with UID [ZZZZZZZZZZZZZ] not found.
{
"version": "1.0",
"statusCode": 412,
"message": "You cannot create a task for a project in the state [Complete]."
}
POST /api/v1/task/review_asset_ext
Creates a new External Review Asset Task for someone who doesn’t have an account in Approval Studio.
The flow is the following:
When a task is created, an email is sent to an email address from the request.
Email contains a link (URL) to a proof report review session.
Approve or reject terminates the review task and makes the URL expire.
Request
{
"projectUID": "XXXXXXXXXXXXXX", // Project this task belongs to, mandatory.
"email": "string", // User's email, mandatory.
"assetUIDs": [
"AAAAAAAAAAAAAAAA1", // One or more assets to review, namdatory.
"AAAAAAAAAAAAAAAA2"
],
"dueDate": "2020-12-04", // Task due date, UTC, optional.
"password": "string", // Optional password. When provided, the reviewer is asked
// to enter it before the review session.
"emailSubject": "string", // Custom email subject line; override template's one. Optional.
"emailLanguage": "English", // Email language, optional. English is default.
// English, German, French, Polish, Spanish, Hebrew, Ukrainian.
"comment": "comment text" // Comment text, optional.
"isAllowDownloadAssets": true, // When true, allows user to download original file.
"isReadOnly": true // When true, makes a review session read-only: no annotations,
// no comments, no approve/reject. Optional.
}
{
"version": "1.0",
"statusCode": 404,
"message": "Annotation not found."
}
HTTP Code
Response
412
Error: Only the user that created the annotation or comment can delete it. You cannot delete other’s users’ annotations and this annotation does not belong to you. Deletion failed.
{
"version": "1.0",
"statusCode": 404,
"message": "You can delete only your annotation."
}
{
"version": "1.0",
"statusCode": 200,
"message": "Annotation was uncompleted."
}
HTTP Code
Response
400
Error: Parameters’ validation failed.
See HTTP code 400 description.
404
Error: Annotation with the given ID not found.
406
Error: Annotation is already completed.
{
"version": "1.0",
"statusCode": 404,
"message": "Annotation not found."
}
Users management
Method/Path
Description
GET /api/v1/users
Returns all clients(tenants) with users.
GET /api/v1/user/loggedin
Returns currently logged in user user.
GET /api/v1/users
This method returns a list of available active users per tenant (client) and a template list for every client.
Please read more about the concept of project templates in the project methods’ group. Curl:
This method returns a currently logged in user; this is the used that was used when creating an authorization token in method POST /api/v1/token/login. Curl:
Approval Studio API uses webhooks to notify your application when an event happens. Webhooks are particularly useful for asynchronous events like when an asset is accepted or rejected or when a new task is created or someone made a comment or a new asset version is uploaded etc.
Begin using the webhooks in three steps:
Create a webhook endpoint on your server.
Register the endpoint with Webhook management method POST /api/v1/webhook.
Test it to ensure that you can receive events using method PUT /api/v1/webhook/test.
Webhooks generally refer to a combination of elements that collectively create a notification and reaction system within a larger integration.
The webhook endpoint is code on your server, which could be written in C#, Java, Ruby, PHP, Node.js, or any other language/technology you prefer. The webhook endpoint has an associated URL (e.g., https://example.com/webhook). Note: Explanations on how to build an endpoint are out of the scope of this document.
The Approval Studio notifications are Event objects. Those event objects contain all the relevant information about what just happened, including the type of event and the data associated with that event. The webhook endpoint uses the event details to take any required actions.
Security
The API host provides a Secret ID with every event object posted on an endpoint. The endpoint needs to check against this ID for every incoming post to avoid spamming. Keep secret id safe.
Retry logic
Webhook host implements a simple retry logic in order to try to deliver events in case of possible troubles on the endpoint side
If the endpoint does not return HTTP code 200, the webhooks host starts retrying posting the same event object up to ~30 minutes. After that time the event delivery silently fails.
Event object
An event object is a JSON document that API posts on a selected endpoint. It generally has the following structure:
{
"EventId":"DY3h1Pl040uIRvL74oKFlQ", // Unique event id.
"EventType":"annotation.added", // Codename of the event, see below.
"Created":"2021-02-18T14:08:08.615088Z", // UTC datetime when the event was generated.
"Data": { // Data block, event-type dependent.
"SomeData": "XXXXXXXX"
}
}
EventID is unique for every Event object. If for whatever reason, the API host makes more than one post on your endproint with the same event object, you can identify it by reading EventID. Event types are self-explanatory:
Event code
Description
project.created
Fires when a new project is created.
project.edited
Fires when a project’s attribute changes, like name, description, due date, etc.
project.state
Fires when project state changes.
asset.uploaded
Fires when an asset or a new version of an existing asset is uploaded.
asset.deleted
Fires when asset deleted.
refdoc.uploaded
A new reference document uploaded.
refdoc.deleted
An existing reference document is deleted.
annotation.added
An annotation to asset is created.
annotation.edited
An annotation is edited.
annotation.deleted
An annotation is deleted.
task.created
A new task of any type is created.
task.completed
A task is marked as completed.
task.deleted
A task is deleted.
task.approved
An asset review task marked as approved.
task.rejected
An asset review task marked as rejected.
webhook.test
Dummy event object for the testing endpoint.
project.created
Fires when a new project is created.
{
"EventId": "XppRxqUyNEqYrZtY9lRBdA",
"EventType": "project.created",
"Created": "2021-02-18T23:22:33.2944308Z",
"Data": {
"ProjectUID": "B0CADA6D72824F85A38BE8471503D204", // Unique ID of a newly created project.
"Name": "ProjectName plain text", // Project name.
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
"ProjectUID": "XXXXXXXXXXXX",
"ProjectState": "OnHold",
"Name": "string",
"Customer": "string",
"Project": "string",
"Design": "string",
"Revision": "string",
"Description": "string",
"Tags": [
"string",
"string"
],
"ReviewStatus": {
"PendingCount": 1,
"ApprovedCount": 2,
"RejectedCount": 3
},
"Created": "2021-04-29T11:56:44.690266Z",
"Owners": [
"YYYYYYYYYYYY0",
"YYYYYYYYYYYY1"
],
"Client": {
"ClientUID": "ZZZZZZZZZZZZ",
"Name": "string"
},
"FolderUID": "string",
"Workflow": {
"WorkflowUID": "string",
"Name": "string"
}
}
}
}
project.edited
Fires when one of the project’s attributes is changed: Name, Customer, Project, Design, Revision, Description, Tags, DueDate, ProjectOwners.
{
"EventId":"xDPuRZ1F_Ea03fO-WPZqnQ",
"EventType":"project.edited",
"Created":"2021-02-18T23:47:17.7572002Z",
"Data": {
"ProjectUID":"XXXXXXXXXXXXXXXXXX", // Unique ID of a project where the change made.
"Attribute":"Name", // Attribute name, see the list above.
"Value":"New project name", // New attribute value.
"Project" : { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
}
}
}
project.state
Fires when the project’s state is changed, interactively or automatically by Approval Studio itself.
{
"EventId": "xDPuRZ1F_Ea03fO-WPZqnQ",
"EventType": "project.edited",
"Created": "2021-02-18T23:47:17.7572002Z",
"Data": {
"ProjectUID": "XXXXXXXXXXXXXXXXXX", // Unique ID of a project where the change made.
"Attribute": "Name", // Attribute name, see the list above.
"Value": "New project name", // New attribute value.
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
}
}
}
asset.uploaded
Fires when an asset (or an asset version) is uploaded and successfully processed. If asset processing fails due to any possible reason, an event is not sent.
{
"EventId": "inuBFhnHn0CUZ4u4OO-8Ww",
"EventType": "asset.uploaded",
"Created": "2021-02-19T12:57:53.9413529Z",
"Data": {
"ProjectUID": "XXXXXXXXXXXXXXXXXX",
"AssetUID": "YYYYYYYYYYYYYYYYYY",
"Name": "filename.png",
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
}
}
}
asset.deleted
Fires when an asset (or an asset version) is deleted. Note: when an asset is deleted, all the related objects – tasks, comments, attachments – are deleted as well, but you will not get separate webhook calls for them.
{
"EventId": "__Z6LClFFkyxeEPeVx-ytQ",
"EventType": "asset.deleted",
"Created": "2021-02-19T13:12:39.2669051Z",
"Data": {
"ProjectUID": "XXXXXXXXXXXXXXXXXX",
"AssetUID": "YYYYYYYYYYYYYYYYYY",
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
}
}
}
refdoc.uploaded
Fires when a reference document is uploaded and processed successfully.
{
"EventId": "q2bwNSmAoUO0wXMVTyn7Cg",
"EventType": "refdoc.uploaded",
"Created": "2021-02-19T13:33:57.6370653Z",
"Data": {
"ProjectUID": "XXXXXXXXXXXXXXXXXX",
"RefDocUID": "YYYYYYYYYYYYYYYYYY",
"Name": "refdocument.docx",
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
}
}
}
refdoc.deleted
Fires when a reference document is deleted.
{
"EventId": "AT4ShAVLN0Ck7kVhMHYzUw",
"EventType": "refdoc.deleted",
"Created": "2021-02-19T13:37:59.3381091Z",
"Data": {
"ProjectUID": "XXXXXXXXXXXXXXXXXX",
"RefDocUID": "YYYYYYYYYYYYYYYYYY",
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
}
}
}
annotation.added
Fires when an annotation is added to an asset.
This can be a high-level annotation associated with the selected region on the image, or a comment (to an annotation).
{
"EventId": "Vx5S8r4os0K5WlwYFsYRhg",
"EventType": "annotation.added",
"Created": "2021-02-19T13:45:24.7158494Z",
"Data": {
"ProjectUID": "XXXXXXXXXXXXXXXXXX",
"AnnotationUID": "YYYYYYYYYYYYYYYYYY",
"AssetUID": "AAAAAAAAAAAAAAAAAAA",
"Text": "Annotation text",
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
}
}
}
annotation.deleted
Fires when an annotation or comment to an annotation is deleted.
{
"EventId": "HdBv5m13CEaZPBAr4E0AIw",
"EventType": "annotation.deleted",
"Created": "2021-02-19T14:51:23.9392566Z",
"Data": {
"ProjectUID": "XXXXXXXXXXXXXXXXXX",
"AnnotationUID": "YYYYYYYYYYYYYYYYYY",
"AssetUID": "AAAAAAAAAAAAAAAAAAA",
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
}
}
}
task.created
Fires when a task is created. Only a task ID is passed to an Event object.
{
"EventId": "QbLNa0r3UkuLPJ3KZpoDNg",
"EventType": "task.created",
"Created": "2021-02-19T15:10:19.7757392Z",
"Data": {
"TaskUID": "XXXXXXXXXXXXXXXXXX",
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
},
"Task": { // Here is a Task entity as it is
// in the GET /api/v1/task.
"taskUID": "XXXXXXXXXXX",
"projectUID": "YYYYYYYYYYYY",
"projectName": "string",
"clientUID": "ZZZZZZZZZZZZ",
"type": "UploadAssets|UploadRefDocs|ReviewAssets|ExternalReviewAssets|UploadChangedAsset|UploadVideo|ExternalReviewVideo|ReviewVideo",
"status": "Pending|Closed|Approved|Rejected|ApprovedWithChanges",
"created": "2020-11-27T15:39:59.864882",
"closed": "2020-11-27T15:40:51.407384",
"user": {
"userUID": "92AFE33153124F0980E43EF80133FE9B",
"fullName": "John Smith",
"email": "[email protected]"
},
"reviewUrl": string, // URL to launch prooftool for given task.
// Appears only for ReviewAsset task.
"requestedAssetName": "filename.pdf" // Name of the asset, a task references to.
// Appears only in UploadChangedAsset task.
}
}
}
task.deleted
Fires when a task is deleted, interactively, or through API.
{
"EventId": "0Jd-zSoOKU2_PoG6zSb5uQ",
"EventType": "task.deleted",
"Created": "2021-02-19T15:20:58.5833087Z",
"Data": {
"TaskUID": "XXXXXXXXXXXXXXXXXX",
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
},
"Task": { // Here is a Task entity as it is
// in the GET /api/v1/task.
[...]
}
}
}
task.approved
Fires when an asset is approved in a proof tool or using API.
TaskUID is an ID of an asset review task associated with a proof tool session.
{
"EventId": "0Jd-zSoOKU2_PoG6zSb5uQ",
"EventType": "task.deleted",
"Created": "2021-02-19T15:20:58.5833087Z",
"Data": {
"TaskUID": "XXXXXXXXXXXXXXXXXX",
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
},
"Task": { // Here is a Task entity as it is
// in the GET /api/v1/task.
[...]
}
}
}
task.rejected
Fires when an asset is rejected in a proof tool or using API.
TaskUID is an ID of an asset review task associated with a proof tool session.
{
"EventId": "0Jd-zSoOKU2_PoG6zSb5uQ",
"EventType": "task.deleted",
"Created": "2021-02-19T15:20:58.5833087Z",
"Data": {
"TaskUID": "XXXXXXXXXXXXXXXXXX",
"Project": { // Here is a Project entity as it is
// in the GET /api/v1/project method.
[...]
},
"Task": { // Here is a Task entity as it is
// in the GET /api/v1/task.
[...]
}
}
}
webhook.test
Fires when API method PUT /api/v1/webhook/test is invoked. It works like any other real event including a secret UID in an HTTP header Api-Secret.
{
"version": "1.0",
"statusCode": 200,
"message": "GET Request successful.",
"result": [
{
"webhookUID": "XXXXXXXXXXXXXXXXXXXX01",
"url": "http://xxxxx.com/part/of/url01",
"secret": "YYYYYYYYYYYYYYYYYYYYY01", // This secret will be sent with every POST in order
"created": "2021-02-09T09:17:27.904911" // to ensure that this is API host is posting.
},
{
"webhookUID": "XXXXXXXXXXXXXXXXXXXX02",
"url": "http://xxxxx.com/part/of/url02",
"secret": "YYYYYYYYYYYYYYYYYYYYY02",
"created": "2021-02-09T09:17:27.904911"
}
]
}
POST /api/v1/webhook
Sets up a new webhook. Request
{
"url": "string", // Valid URL string, http or https.
"clientUID": "string", // Client UID, optional.
"eventType": "string" // One of the event type names, optional.
}
clientUID is an optional client identificator. Events are client-wide, so in the case of multitenancy, when a user belongs to multiple clients, the events through webhooks are produced based on the client you provided when creating a webhook. You need to install multiple webhooks to get events from all tenants you belong to.
If no clientUID is provided, the first client in the list is used. eventType is an optional event type, please see Event object When provided, it limits the webhook to be invoked only when the given event type occurs. If it’s not provided, all events will be sent to the webhook and in this case an API consumer is responsible for filtering events (when necessary).
Note: The API host might need up to ~1 minute to start processing a newly installed webhook. Curl:
Success. A newly created webhook instance returned.
{
"version": "1.0",
"statusCode": 200,
"message": "POST Request successful.",
"result": {
"webhookUID": "XXXXXXXXXXXXXXXXXXXX01", // Newly assigned webhook ID.
"url": "http://xxxx.com/part/of/url", // Url of the webhook, as in the request.
"secret": "YYYYYYYYYYYYYYYYYYYYY01", // This secret will be sent with every POST in order
"created": "2021-02-09T09:17:27.904911" // to ensure that this is API host is posting,
// see HTTP response header "Api-Secret".
}
}
HTTP Code
Response
400
Error: Parameters’ validation failed.
See HTTP code 400 description.
412
Error: Webhook with the given URL is already registered for this tenant. API does not allow to setup duplicates.
DELETE /api/v1/webhook
Deletes a webhook with the given ID.
Note that deletion of a webhook might need up to ~1 minute for API host to update. Curl:
When posting test data, the API host uses the same retry logic as it is for real calls, i.e. tries to re-deliver it in case of failure, so multiple calls are expected if the endpoint fails to accept the call instantly. Curl: