The InDesign Cloud Services enables you to make edit, query data, and run workflows on an ID file. This document will help you onboard to the services, familiarize you with the available features, and get you started with some basic usage examples.
- The user should be registered on Developer Pre-release program (This would bind the developer to NDA).
- The user should fill up this form for being a part of the Beta program of InDesign Cloud Services.
After this, we will be shortlisting and enroll the developers in the beta program. We will be sharing the client_id and client_secret and other relevant details with individual developers.
You must generate an access token using the details shared above and follow these steps to setup:
- Download the node and install it on your machine.
- Download and extract the sample code.
- Edit the contents of the config file (config.js) by replacing relevant data for clientId , clientSecret, and other attributes from the data shared with you at the time of acceptance.
- Execute.
npm install node app.js
After successfully completing the above steps, you’ll get an 'access_token' in response. The token will be valid for 24hrs, after which you must re-generate it. Use this token in your API calls to make them work.
InDesign Cloud Services support two types of authentication :
-
Service Account Integration: For service-to-service integrations, you will need a JSON Web Token (JWT) that encapsulates your client credentials and authenticates the identity of your integration. You then exchange the JWT for the access token that authorizes access.
-
OAuth integration: (Coming soon) If your integration needs to access content or a service on behalf of an end user, that user must be authenticated as well. Your integration must pass the OAuth token granted by the Adobe IMS.
Here’s a skeleton cURL request to accessing the APIs :
curl --location --request POST <endpoint> \ --header 'Authorization: bearer <access_token>' \ --header 'x-api-key: <client_id>' \ --header 'Content-Type: application/json' \ --data-raw '{ "assets": [ ... ], "params": { ... }, "outputs": [ ... ] }
You can use InDesign Cloud Services in two ways:
- Consume the APIs provided by InDesign Cloud Services. You can find the API documentation here.
- Expose your own APIs with the help of custom scripts. You can find the documentation here.
We will cover both scenarios in the coming sections, but first, let us go over the common points. We'll discuss various points below and; their examples can be seen in conjunction with the API documentation shared above.
As shown in the skeleton request above, there are three main parts of the body of the request. Here’s the information to understand these parts and their significance:
-
"assets": This part is where the caller can specify input assets for the request to be processed successfully. More information can be found below.
-
"outputs": Specify the locations where to upload the output assets. You can find More more details can be found herebelow. In the absence of this, the outputs assets are stored in a temporary repository, and a pre-signed URL will be shared for those assets, which will be valid for 24hrs.
-
"params": Specify information regarding what to do with the input assets.
You can refer to API documentation for more details.
The platform supports multiple asset types. These asset types signify storage repositories from which the platform can download. You can provide the input asset information within the "assets" array . Here are the supported types :
| Type | Required Parameter | Nature | Notes |
|---|---|---|---|
| HTTP_GET | url | mandatory | Pre-signed URL |
HTTP_GET example
{
"source" : {
"type" : "HTTP_GET",
"url" : "https://xyz-input-asset.s3.amazonaws.com/Template.indt"
},
"destination" : "jobasset/template.indt"
}In all the above examples, you can view that data is divided into source and destination. The first attribute, 'source' is where the asset is downloaded from. The second attribute 'destination' refers to the location where the asset would be downloaded to. You can find more information in below sections.
Like input assets, the platform supports multiple asset types for output as well. These asset types signify storage repositories to which platform can upload. You can provide this information in the "outputs" array within the body of the request.
Here are the supported types:
| Type | Required Parameter | Nature | Notes |
|---|---|---|---|
| HTTP_PUT | url | mandatory | Pre-signed URL |
| HTTP_POST | url | mandatory | Pre-signed URL |
HTTP_PUT or HTTP_POST example
{
"destination" : {
"type" : "HTTP_POST",
"url" : "https://xyz-input-asset.s3.amazonaws.com/AdobeStock_322173431.indt"
},
"source" : "jobasset/template.indt"
}URL should be a pre-signed POST URL in case of HTTP_POST and in case type is HTTP_PUT, URL should be a pre-signed PUT URL.
Here are the supported storage types to refer your assets from:
- AWS S3: Use a presigned GET/PUT/POST URL
- Dropbox: Generate temporary upload/download links using link
- Azure: Use a Shared Access Signature (SAS) in Azure Storage, for GET/PUT/POST operations.
Links is one of the most important features of InDesign. You can place and link content within the same document or even across different documents. This also helps in keeping the assets and the document decoupled. Links can be corresponding to texts, graphics etc.
- InDesign APIs support the processing of documents with links.
- To process a request, a temporary folder/directory is created. which is called as the working directory for the request.
- All the input assets mentioned in the request are downloaded and kept in the working directory.
- Within the working directory the location of individual asset is governed by the relative path mentioned in the 'destination' attribute.
- Please note, that to refer to the same asset in the rest of the params, the value mentioned in the destination property is to be used.
You can use the following ways to make links work, it can be done in two ways:
- Maintaining relative paths of assets to the target document. While doing this, you need to place the files outside of the working directory.
- If you place the linked assets parallel to the target document, the links get resolved and the assets are picked.
Sometimes the documents contain custom links which are not understood by InDesign. To enable proper execution of the job, the custom URLs can be relinked to assets provided in the request. Here’s an example for this:
{
"params": {
"generalSettings": {
"links": {
"replaceLinks": [
{
"targetDocument": "TargetDocument.indd",
"mapping": [
{
"currentURI": "customScheme:4c189e2d-315e-4fab-a8c2-45690e44d1f0",
"newAssetRelativePath": "SomeNewAsset.png"
}
]
}
]
}
}
}
}In this example the existing URI "customScheme:4c189e2d-315e-4fab-a8c2-45690e44d1f0" in document "TargetDocument.indd" cannot be interpreted by InDesign by itself. The caller would have provided an input asset with "destination" attribute as "SomeAsset.png".
By using the above example the caller is asking to relink the links with specified URI to be relinked to the new asset which is present at <Working_Directory>/SomeNewAsset.png
Just like links, fonts are also very important. The support of fonts is as follows:
Adobe fonts are currently supported only with OAuth integration where the end user can be identified. These are not yet supported with Service account integration.
- The fonts are fetched automatically, on behalf of the requestor and thus nothing needs to be done while making a request.
- The list of supported fonts is dependent on the account used to make the call.
- Platform iterates over all the InDesign documents brought in the temporary working directory. Then pre-job is executed.
- As a pre-job step, these documents are opened and, the list of Adobe fonts is extracted from it. These documents are closed, and fonts are downloaded.
- When the fonts' download is complete, the actual job script is run.
Here are cases where the search from Adobe Fonts will not help :
-
When the Adobe fonts are not being used in the document, hence it does not make sense to open the document and search for those.
-
Where the service account integration is used for connecting with the APIs.
In these scenarios, the caller has the option to skip the font search. For more details please look at the Optimisation section. Here’s an example, where a specific document is to be searched for Adobe Fonts:
{
"params": {
"generalSettings": {
"fonts": {
"adobeFonts": {
"includeDocuments": [
"TargetDocument.indd"
]
}
}
}
}
}For more information around this, please refer to the API documentation.
Custom fonts or user fonts can be provided as a regular asset. Here’s an example:
{
"assets":[
{
"source": {
"url":"<YOUR PRE-SIGNED URL>",
"type":"HTTP_GET"
},
"destination" : "Cheese_final.indd"
},
{
"source": {
"url":"<YOUR PRE-SIGNED URL>",
"type":"HTTP_GET"
},
"destination" : "FontName.otf"
}
]
}For the fonts to be picked properly, please place it in the "Document Fonts" folder parallel to the document which uses it. Or, if the fonts are kept under some other folder say like "fontFolder", please specify the font directory as follows:
{
"params": {
"generalSettings": {
"fonts": {
"fontsDirectories": [
"fontFolder"
]
}
}
}
}In absence of any font directory being mentioned, the working directory will be added as the font directory.
There are certain optimizations which a user can employ to make the APIs more performant.
- If the font directories are to be added, don’t use the directories with InDesign documents, as opening of these files will create additional lock files and will in turn trigger recalculation of the font resources. As a best practice, try to keep the fonts in "Document Fonts" or in an isolated directory. If all the hierarchy of the downloaded fonts have been properly mentioned as lying in "Document Fonts" folder parallel to individual documents then following can be used to bring in a level of optimization. This will avoid addition of any font directory and might thus result in performance benefits.
{
"params": {
"generalSettings": {
"fonts": {
"fontsDirectories": []
}
}
}
}- Skipping the Adobe fonts search is another way to optimize the call. It can be done by providing includeDocuments as an empty array.
{
"params": {
"generalSettings": {
"fonts": {
"adobeFonts": {
"includeDocuments": []
}
}
}
}
}Now that the request is sent, how can one get the status of the request. This is demonstrated with an example below. Suppose the user triggers a rendition call with a 3 page document, the request will look something like this:
curl --location --request POST 'https://indesign.adobe.io/api/v1/capability/indesign/rendition/png' \
--header 'Authorization: bearer <access_token>' \
--header 'x-api-key: <client_id>' \
--header 'Content-Type: application/json' \
--data-raw '{
"assets":[
{
"source": {
"url":<pre-signed url>,
"type":"HTTP_GET"
},
"destination" : "3PageDoc.indd"
}
],
"params":{
"jobType":"RENDITION_PNG",
"targetDocuments": [
"3PageDoc.indd"
],
"pageRange": "1-3",
"outputFileBaseString": "template_rendition"
}
}'
The response to the request will be something like
{
"statusUrls": {
"latest": "https://indesign.adobe.io/api/v1/capability/status/ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"all": "https://indesign.adobe.io/api/v1/capability/status/all/ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85"
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85"
}"id": Corresponds to the jobID. Use this to know the status."latest": Use this to get the latest status event of the job."all": Use this to get all the status events in a paginated format.
Latest request Use this to get the latest event generated in the process.
curl --location --request GET 'https://indesign.adobe.io/api/v1/capability/status/ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85' \
--header 'Authorization: bearer <access_token>' \
--header 'x-api-key: <client_id>'
Latest response
{
"eventId": "8175851e-f122-464c-9d02-fe08e7d6fc0f",
"data": {
"outputs": [
{
"renditions": [
{
"pageIndex": 1,
"path": [
"tmp964721/template_rendition.png"
]
},
{
"pageIndex": 2,
"path": [
"tmp964721/template_rendition2.png"
]
},
{
"pageIndex": 3,
"path": [
"tmp964721/template_rendition3.png"
]
}
],
"input": "3PageDoc.indd"
}
]
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "COMPLETED",
"timestamp": 1623913539469
}All request
curl --location --request GET 'https://indesign.adobe.io/api/v1/capability/status/all/ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85' \
--header 'Authorization: bearer <access_token>' \
--header 'x-api-key: <client_id>'
All response
{
"events": [
{
"eventId": "8175851e-f122-464c-9d02-fe08e7d6fc0f",
"data": {
"outputs": [
{
"renditions": [
{
"pageIndex": 1,
"path": [
"tmp964721/template_rendition.png"
]
},
{
"pageIndex": 2,
"path": [
"tmp964721/template_rendition2.png"
]
},
{
"pageIndex": 3,
"path": [
"tmp964721/template_rendition3.png"
]
}
],
"input": "3PageDoc.indd"
}
]
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "COMPLETED",
"timestamp": 1623913539469
},
{
"eventId": "7e48fd7e-8ffc-4439-b315-3f31da111cb4",
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "ASSETS_UPLOAD_COMPLETED",
"timestamp": 1623913539462
},
{
"eventId": "ff08253f-2024-4ab3-b52e-67715fbc7f9f",
"data": {
"sizeInBytes": 7489,
"destination": {
"type": "S3",
"url": <presigned url for temporary asset>
},
"uploadTimeMillis": 238,
"source": "tmp964721/template_rendition2.png"
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "ASSET_UPLOAD_COMPLETED",
"timestamp": 1623913539375
},
{
"eventId": "ab01e522-deeb-41b8-a0c9-c662691b496f",
"data": {
"sizeInBytes": 8519,
"destination": {
"type": "S3",
"url": <presigned url for temporary asset>
},
"uploadTimeMillis": 185,
"source": "tmp964721/template_rendition3.png"
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "ASSET_UPLOAD_COMPLETED",
"timestamp": 1623913539323
},
{
"eventId": "8d264064-d426-4773-8a07-05336dbc1c73",
"data": {
"sizeInBytes": 4128,
"destination": {
"type": "S3",
"url": <presigned url for temporary asset>
},
"uploadTimeMillis": 172,
"source": "tmp964721/template_rendition.png"
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "ASSET_UPLOAD_COMPLETED",
"timestamp": 1623913539308
},
{
"eventId": "fe894b58-2cd9-4184-8d16-ab2c988b7f8f",
"data": {
"destination": {
"type": "S3"
},
"source": "tmp964721/template_rendition2.png"
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "ASSET_UPLOAD_STARTED",
"timestamp": 1623913539202
},
{
"eventId": "39278fe7-482d-411c-adc0-3917b62b1f05",
"data": {
"destination": {
"type": "S3"
},
"source": "tmp964721/template_rendition3.png"
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "ASSET_UPLOAD_STARTED",
"timestamp": 1623913539196
},
{
"eventId": "0a7940cf-411f-48be-84d6-d737623c34e1",
"data": {
"destination": {
"type": "S3"
},
"source": "tmp964721/template_rendition.png"
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "ASSET_UPLOAD_STARTED",
"timestamp": 1623913539154
},
{
"eventId": "3bfff3a6-895f-41ae-a280-3a0fd4e67ef0",
"data": {
"total": 1
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "ASSETS_UPLOAD_STARTED",
"timestamp": 1623913539134
},
{
"eventId": "4201e4ad-f225-42ad-b3f7-a8b66bb86926",
"data": {
"percent": 100
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "RUNNING",
"timestamp": 1623913539085
}
],
"paging": {
"prevUrl": "https://indesign.adobe.io/api/v1/capability/status/all/ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85?to=1623913539084",
"nextUrl": "https://indesign.adobe.io/api/v1/capability/status/all/ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85?from=1623913539470"
}
}Please Note: You can use the nextUrl to retrieve further status events.
Here’s an example to check for specific events, please refer to following example, where "ASSET_UPLOAD_COMPLETED" event is looked for.
curl --location --request GET 'https://indesign.adobe.io/api/v1/capability/status/all/ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85?state=ASSET_UPLOAD_COMPLETED' \
--header 'Authorization: bearer <access_token>' \
--header 'x-api-key: <client_id>'
Here’s the response corresponding to it :
{
"events": [
{
"eventId": "ff08253f-2024-4ab3-b52e-67715fbc7f9f",
"data": {
"sizeInBytes": 7489,
"destination": {
"type": "S3",
"url": <presigned url for temporary asset>
},
"uploadTimeMillis": 238,
"source": "tmp964721/template_rendition2.png"
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "ASSET_UPLOAD_COMPLETED",
"timestamp": 1623913539375
},
{
"eventId": "ab01e522-deeb-41b8-a0c9-c662691b496f",
"data": {
"sizeInBytes": 8519,
"destination": {
"type": "S3",
"url": <presigned url for temporary asset>
},
"uploadTimeMillis": 185,
"source": "tmp964721/template_rendition3.png"
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "ASSET_UPLOAD_COMPLETED",
"timestamp": 1623913539323
},
{
"eventId": "8d264064-d426-4773-8a07-05336dbc1c73",
"data": {
"sizeInBytes": 4128,
"destination": {
"type": "S3",
"url": <presigned url for temporary asset>
},
"uploadTimeMillis": 172,
"source": "tmp964721/template_rendition.png"
},
"id": "ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85",
"state": "ASSET_UPLOAD_COMPLETED",
"timestamp": 1623913539308
}
],
"paging": {
"prevUrl": "https://indesign.adobe.io/api/v1/capability/status/all/ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85?state=ASSET_UPLOAD_COMPLETED&to=1623913539307",
"nextUrl": "https://indesign.adobe.io/api/v1/capability/status/all/ee9f6ee4-ea8c-40d5-a548-f7a0e5a2ca85?state=ASSET_UPLOAD_COMPLETED&from=1623913539376"
}
}You can find the detailed API documentation here. Here are some sample requests for the APIs :
Creates and returns new PDF from a specific InDesign document. The following example uses pre-signed URL and a custom font
curl --location --request POST 'https://indesign.adobe.io/api/v1/capability/indesign/rendition/pdf' \
--header 'Authorization: bearer <YOUR_OAUTH_TOKEN>' \
--header 'x-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data-raw '{
"assets":[
{
"source": {
"url":"<YOUR PRE-SIGNED URL>",
"type":"HTTP_GET"
},
"destination" : "Cheese_final.indd"
},
{
"source": {
"url":"<YOUR PRE-SIGNED URL>",
"type":"HTTP_GET"
},
"destination" : "Abelone-FREE.otf"
}
],
"params":{
"jobType":"RENDITION_PDFPRINT",
"targetDocuments": [
"Cheese_final.indd"
],
"outputFileBaseString": "template_rendition"
}
}
Retrieves the data merge tags from the document.
curl --location --request POST 'https://indesign.adobe.io/api/v1/capability/indesign/dataMerge/tags' \
--header 'Authorization: bearer <YOUR_OAUTH_TOKEN>' \
--header 'x-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data-raw '{
"assets": [
{
"source": {
"url":"<YOUR PRE-SIGNED URL>",
"type":"HTTP_GET"
},
"destination" : "dataMergeTemplate.indd"
},
{
"source": {
"url":"<YOUR PRE-SIGNED URL>",
"type":"HTTP_GET"
},
"destination": "batang.ttc"
}
],
"params": {
"jobType": "DATAMERGE_TAGS",
"targetDocument": "dataMergeTemplate.indd",
"includePageItemIdentifiers": true
}
}
Creates and returns merged InDesign documents or PDFs that are created after merging the data and the given template.
curl --location --request POST 'https://indesign.adobe.io/api/v1/capability/indesign/dataMerge/merge' \
--header 'Authorization: bearer <YOUR_OAUTH_TOKEN>' \
--header 'x-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data-raw '{
"assets": [
{
"source": {
"url":"<YOUR PRE-SIGNED URL>",
"type":"HTTP_GET"
},
"destination" : "dataMergeTemplate.indd"
},
{
"source": {
"url":"<YOUR PRE-SIGNED URL>",
"type":"HTTP_GET"
},
"destination": "Directory_Names.csv"
}
],
"params": {
"jobType": "DATAMERGE_MERGE",
"targetDocument": "dataMergeTemplate.indd",
"outputType": "PDF",
"outputFolderPath": "outputfolder",
"outputFileBaseString" : "merged"
"dataSource": "Directory_Names.csv"
}
"outputs": [ // custom user output
{
"destination": {
"type": "HTTP_PUT",
"url": "<YOUR PUT-SIGNED URL>"
},
"source": "outputfolder/merged.pdf"
}
]
}
Many times, the requirements of the end users are very specific and cannot be fulfilled in a generic manner. Some custom work may be needed to address these cases,.
InDesign Cloud Services exposes a way for third- party developers to come onboard and deploy their custom scripts as end points. The script writer can define the custom attributes and values which will make sense for a particular endpoint. These can be done by deploying the capability bundle. To understand more about capabilities, their deployment and using them, please refer to this documentation.
There are few points which must be kept in mind while writing a script for InDesign Cloud Services.
-
To run a script with InDesign Cloud Services, the script must be compatible to run with InDesignServer. However, any script that can be run on InDesignServer can't be run as is.
-
While writing a new script or modifing exisiting scripts for InDesign Cloud Services, there are few nuances which the developer must takecare with respect to "input to the script" and "output" from script”. These nuances are discussed in the next few sections.
-
Case 1 : Script does not require any input/argument.
In this case, system by default send string type argument named
"parameters"as following:{ "assets": [ {"path": "doc.indd"}, {"path": "image.pdf"}, ... ], "params": { }, "jobID": "0c531425-bc82-43c0-89b7-0e851cd56061", "workingFolder": <Some path> }The above mentioned json will be received in the form of
"string". Which further needs to be parsed inside the script to retrive the value of attributes. In this case"params"attribute will be empty. Since, the script does not need an argument. -
Case 2 : Script accepts some input argument. In this case, system by default send string type argument named
"parameters"which also, include input arguments e.g. "arg1", "arg2".So, In order to use the argument
"parameters"must be parsed. And then you must extract the value of arg1 and arg2.{ "assets": [ {"path":"doc.indd"}, {"path":"image.pdf"}, ... ], "params": { "arg1": <data corresponding to argument1>, "arg2": <data corresponding to argument2>, ... }, "jobID": "0c531425-bc82-43c0-89b7-0e851cd56061", "workingFolder": <Some path> }You must tweak the existing scripts to accept the arguments correctly e.g.
Old Script New Script var arg1 = app.scriptArgs.get('argument1')
var arg2 = app.scriptArgs.get('argument2')
// Some processingvar parameters = app.scriptArgs.get('parameters')
// parse "parameters" so, that values can be extracted.
var arg1 = parameters['argument1']
var arg2 = parameters['argument2']
// Some processingThe execution of any script depends on the following attributes:
Attribute Input Request Mapping Description assets assets->destination field This contain list of input assets. like indd,pdf or jpeg etc. params params User input/arguments that are used inside script jobID Auto generated The job ID workingFolder Auto generated The working folder for the job. This is the base directory. Inside this directory all the assets and scripts downloaded. e.g c:\\baseFolder\assets
Here’s the sample input and sample script code to open document and close a document.
- Sample Input request body
{ "assets": [ { "source": { "type": "HTTP_GET", "url": "Pre-signed url of document" }, "destination": "doc.indd" } ], "params": { "targetDocument": "doc.indd" } } - Transformed Input request. That is sent to script
{ "assets": [ { "path": "doc.indd" } ], "params": { "targetDocument": "doc.indd" }, "jobID": "0c531425-bc82-43c0-89b7-0e851cd56061", "workingFolder": "c:\\baseFolder\\assets" } - Sample code that takes above mentioned input. This code opens docuemnt and closes the document.
var input = app.scriptArgs.get('parameters') var allParameters = JSON.parse(input) // Set the working folder. This is the directory within which all the input and output assets are to be managed. var basePath = allParameters["workingFolder"] var documentToOpen = allParameters["params"]["targetDocument"] documentPath = basePath + "\\" + documentToOpen document = app.open(File(documentPath)) document.close()
- Sample Input request body
A developer must follow certain rules in order to output data, file or log from a script. Please follow these instructions to provide output correctly :
-
Execution is successful
The following attributes are expected in return as json string, if the script execution is successful.
{ "status": "SUCCESS", "assetsToBeUploaded": [ { "path": <Relative path of file to be uploaded w.r.t working folder>, "data": <Data in dictionary (object) format to be associated with this asset> } ], "dataURL": <Relative path of json file w.r.t working folder> }Caution: Anything outside of these attributes might be logged as data to be investigated.
Attribute Description Optional/Mandatory dataURL This should have path of json file w.r.t working folder. And it should be created inside working folder Mandatory status Status of execution (SUCCESS/FAILURE) Mandatory assetToBeUploaded Array for assets that need to uploaded. This can be empty Mandatory
-
Here’s a sample code returning a successful execution. Without data and without any output file.
/* Creates object to be returned when job is successful. object should be stringify before returning. */ function GetSuccessReturnObj() { var obj = {} obj.status = 'SUCCESS' obj.assetsToBeUploaded = [] obj.dataURL = '' return JSON.stringify(obj) }
-
Here’s a sample code returning a successful execution. With data and without any output file.
/* Creates object to be returned when job is successful. Data is written into a json file, which should be created inside working folder. @param data: The data in dictionary (object) format to be returned back. Object should be stringifiedy before returning. */ function GetSuccessReturnObj(data) { var obj = {} obj.status = 'SUCCESS' obj.assetsToBeUploaded = [] obj.dataURL = WriteToFile(data) return JSON.stringify(obj) } function WriteToFile ( data ) { var newFile var fileName = 'data.json' var filePath = workingFolder + '\\' + fileName newFile = File(filePath) newFile.encoding = 'UTF8' newFile.open('write') newFile.write(JSON.stringify(data)) newFile.close() return filePath }
-
Here’s a sample code returning a successful execution. With/Without data and with output file.
/* Create array of asset which is to be uploaded and sent back to the caller. assetPath: Path of the file to be uploaded, relative to the working folder. data: The data in dictionary (object) format to be associated with this asset. (It is optional) This data will be provided to the user with ASSET_UPLOAD_COMPLETED event. */ var assets = [] var assetToBeUploaded = {} assetToBeUploaded.path = assetPath assetToBeUploaded.data = data //this is optional assets.push(assetToBeUploaded) function GetSuccessReturnObj(assets, data) { var obj = {} obj.status = 'SUCCESS' obj.assetsToBeUploaded = assets if (data) { obj.dataURL = WriteToFile(data) } else { obj.dataURL = '' } return JSON.stringify(obj) }
-
In the above cases, it can be observed that the data is being shared in a json file, and not directly. This is to take care of cases where the data becomes too big to send back.
-
In case no data is to be sent, empty string should be passed in 'dataURL'.
-
-
Execution failed
In case of failed execution of the script, the following attributes are expected in return as json string.
{ "status": "FAILURE", "errorCode": <Error code>, "errorString": <Error Message>, }Attribute Output Request Mapping Meaning status Status of execution (SUCCESS/FAILURE) Mandatory errorCode ErrorCode of the error Optional errorString Description of error Optional Here’s a sample code to use as a starting point, to create the return object for failed cases.
/* Creates json string that is returned in case the job has failed. @param errorCode: Error code detail. @param errorString: Description about error. @return: json string. */ function GetFailureReturnObj(errorCode, errorString) { var obj = {} obj.status = '‘FAILURE'’ obj.errorCode = errorCode obj.errorString = errorString return JSON.stringify(obj) }
While writing your own scripts, debugging forms an important part of the whole process. Likewise, to keep track of what decisions were made during a script execution, one may feel the need to log the steps. You can log the data during script execution. This can be done in two ways
- Collecting all the logs in an array and then dumping them with a function similar to WriteToFile. This must be accompanied with addition of the relative path to list of assets to be uploaded.
- Second way is to log data in the application's log. You can use the following script calls to redirect the provided log to application's log.
You can dump the application's log into a file, with the addition of
// The following should come in the application log, which can be dumped using generalSettings/appLogs/logsRelativePath app.consoleout('Logging in app\'s std::out') app.consoleerr('Logging in app\'s std::err')
"generalSetting"as mentioned below:."params": { "targetDocument": "doc.indd", "outputPath": "idmlDoc.idml", "generalSettings": { "appLogs": { "logsRelativePath": "appLog.txt" } } }
A sample script can be found under Example. where the main script is sample.jsx and rest are supporting scripts.
- This script has the functionality to create
idmlfrom indesign document. - This script can be treated as a baseline script that has the handling of input and output.
Here are a few things that a script writer must keep in mind while writing scripts. These points are:
- Set appropriate preferences: Many times the script execution is dependent on the preferences set for the application or the document. Before executing the relevant portion of script, please ensure that the desired preferences are set. As a good practice, reset the preferences to their original value once the execution is complete.
- No socket programming: The container running the script is a closed one and any kind of socket programming is discouraged.
- Work within the working folder: For a job, working folder is the designated space for the script to work on. Scripts are supposed to be working on files within this and are not supposed to look outside.
- Code Readability Requirements: Developers must not obfuscate the code or conceal the functionality of their capability. This also applies to any external code or resource fetched by the extension package. Minification is allowed, including the following forms:
- Removal of whitespace, newlines, code comments, and block delimiters
- Shortening of variable and function names
- Collapsing files together
- Refrain from performing the following activities:
- Facilitate unauthorized access to content on websites, such as circumventing paywalls or login restrictions
- Encourage, facilitate, or enable the unauthorized access, download, or streaming of copyrighted content or media
- Enumerate system resources such as files, networking configuration, etc.
- Mine cryptocurrency
Here are a few limitations to the APIs you should be aware of ahead of time:
- Error handling is a work in progress. Sometimes you may not see the most helpful of messages.
For increased reliability and stability we have added a retry mechanism for all API calls, and here are some recommendations on how to handle these:
- You should only retry requests that have a 5xx response code. A 5xx error response indicates there was a problem processing the request on the server.
- You should implement an exponential back-off retry strategy with 3 retry attempts.
- You should not retry requests for any other response code.