InDesign API Key Concepts
Consider these important concepts when using InDesign APIs.
Pre-signed URLs
What is a pre-signed URL?
A pre-signed URL is a URL that grants temporary access to a specific resource, typically in cloud storage, with predefined permissions and an expiration time. It allows users to upload or download files securely without needing direct access to the storage service's credentials.
While using InDesign APIs, the input and output assets are stored as pre-signed URLs.
Input assets
The platform supports multiple asset types for input. These asset types indicate storage repositories from which the platform can download. You can provide the input asset information within the assets array.
InDesign APIs support the following input assets:
-
Azure: Use a Shared Access Signature (SAS) in Azure Storage for GET/PUT/POST operations.
"assets" :[
{
"source" : {
"storageType" : "Azure", //Optional
"url" : "https://xyz-blob.core.windows.net/Template.indt"
},
"destination" : "jobasset/template1.indt"
},
{
"source" : {
"storageType" : "Aws", //Optional
"url" : "https://s3.eu-west-1.amazonaws/xyz/Template.indt"
},
"destination" : "jobasset/template2.indt"
}
]
In the examples above, you can see that data is divided into source and destination.
The source attribute is where the asset is downloaded from. The destination attribute refers to where the asset would be downloaded to.
Output assets
The platform supports multiple asset types for output. These asset types signify storage repositories to which the platform can upload. You can provide this information in the outputs array within the body of the request.
"outputs": [
{
"destination" : {
"type" : "Azure",
"url" : "https://xyz-blob.core.windows.net/Template.indt"
},
"source" : "jobasset/template.indt"
}
]
Each storage provider may have its own requirements for creating PUT or POST pre-signed URLs. Please follow the documentation from the individual storage provider creating these URLs.
About custom script bundles
To create a script to use with the Custom Scripts API, you'll need to prepare a script bundle, a ZIP file with a predefined structure.
Custom script bundle structure
The structure for a simple custom script bundle would look like this:
custom-script-folder
|------ manifest.json
|------ script.js
Custom Script manifest
The manifest file is a plain JSON file with the following structure:
{
"manifestVersion": "1.0.0",
"id": "<Unique ID for the custom script>",
"name": "<Name of the custom script>",
"version": "<x.y.z>",
"host": {
"app": "indesign",
"appVersionStrategy": "latest_version" | "fixed_major_version" | "fixed_major_and_minor_version",
"majorAppVersion": 20, // optional depending on strategy
"minorAppVersion": 1 // optional depending on strategy
},
"apiEntryPoints": [
{
"type": "capability",
"path": "script.js",
"language": "extendscript"
}
]
}
manifestVersionnameversionhost.appindesign.host.appVersionStrategyhost.majorAppVersionhost.minorAppVersionapiEntryPoints<EntryPointDefinition> objects. Describes the API entry points for the custom script.- When a customer registers a script without specifying the strategy, the system automatically chooses latest_version as the default strategy.
- majorAppVersion parameter is mandatory if appVersionStrategy is fixed_major_version.
- majorAppVersion and minorAppVersion are mandatory if appVersionStrategy is fixed_major_and_minor_version.
The apiEntryPoints field
In the manifest file, the apiEntryPoints attribute is an array of EntryPointDefinition objects with the following format:
typecapability.pathlanguage- Each entry point specifies a custom script or a custom script specification.
- There can be only one entry of each type in the array.
- The maximum size of the array is 3.
There's no need to define an entry point if the default values are being used for them.
The script.js file
The script's author defines the custom attributes and values for a particular endpoint using script.js file in the custom script bundle.
The execution of any script depends on the following attributes:
assetsparamsjobIDworkingFolderFor examples, see Writing Scripts for the Custom Scripts API.
Zipping and updating a custom script bundle
When zipping the files, don't place them inside a folder first. Instead, directly select the files and create the ZIP. This way when it's unzipped the files will appear directly instead of appearing inside a folder.
The custom script bundle can be updated by incrementing the version in the script manifest. The updated ZIP bundle can be uploaded using the submission endpoint.
InDesign links support
The InDesign APIs support links to content within the same document or across different documents. This helps keep the assets and the document decoupled.
To handle links, a temporary folder/directory, called the working directory, is created to process a 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 assets is governed by the relative path mentioned in the destination attribute. Note that the value mentioned in the destination property must be used to refer to the same asset in the rest of the parameters.
Links can work in two ways:
-
Maintain relative paths of assets to the target document. To do this, place the files outside the working directory.
-
If you place the linked assets parallel to the target document, the links get resolved, and the assets will be picked.
When documents contain custom links that InDesign does not understand, the custom URLs can be relinked to assets provided in the request.
Relink example
In the example below, the existing URI "customScheme:4c189e2d-315e-4fab-a8c2-45690e44d1f0" in the document "TargetDocument.indd" cannot be interpreted by InDesign. The caller would have provided an input asset with the "destination" attribute as "SomeAsset.png".
In this example the caller is asking the specified URI to be relinked to the new asset, which is present at <Working_Directory>/SomeNewAsset.png.
{
"params": {
"generalSettings": {
"links": {
"replaceLinks": [
{
"targetDocument": "TargetDocument.indd",
"mapping": [
{
"currentURI": "customScheme:4c189e2d-315e-4fab-a8c2-45690e44d1f0",
"newAssetRelativePath": "SomeNewAsset.png"
}
]
}
]
}
}
}
}
Using custom fonts
Custom fonts or user fonts can be provided as a regular asset.
{
"assets":[
{
"source": {
"url":"<PRE-SIGNED URL FOR DOCUMENT>"
},
"destination" : "Cheese_final.indd"
},
{
"source": {
"url":"<PRE-SIGNED URL FOR FONT FILE>"
},
"destination" : "FontName.otf"
}
]
}
Best practices with fonts
For fonts to be found by default, please place them in the "Document Fonts" folder parallel to the document that uses them.
By keeping the fonts in the "Document Fonts" folder parallel to indivdual documents, you can avoid adding any font directory and get a more optimized performance (see below).
{
"params": {
"generalSettings": {
"fonts": {
"fontsDirectories": []
}
}
}
}
Or, if the fonts are kept in some other folder (for example, fontFolder), please specify the correct font directory:
{
"params": {
"generalSettings": {
"fonts": {
"fontsDirectories": [
"fontFolder"
]
}
}
}
}
When font directories are added, don't use them with InDesign documents because opening these files will create additional lock files and trigger recalculation of the font resources.
Pagination
Some list-style responses support pagination using the page and size query parameters. When multiple pages are available, the response includes a paging object with navigation URLs.
For example in case number of outputs is greater than 10 in case of status api execution, the response looks like this, including the pagination block :
{
"jobId": "b50a4f99-4e80-4194-ac2a-043aaddae4ad",
"timestamp": "2025-08-29T16:31:27.741Z",
"status": "succeeded",
"data": {
"outputs": [
{
"renditions": [
{
"pageIndex": 1,
"path": [
"test/test.jpg"
]
},
{
"pageIndex": 2,
"path": [
"test/test2.jpg"
]
},
.
.
.
{
"pageIndex": 16,
"path": [
"test/test16.jpg"
]
}
],
"input": "test_16Pages.indd",
}
]
},
"outputs": [
{
"destination": {
"url": "<presignedURL>"
},
"source": "test\\test1.jpg"
},
{
"destination": {
"url": "<presignedURL>"
},
"source": "test\\test2.jpg"
},
.
.
.
{
"destination": {
"url": "<presignedURL>"
},
"source": "test\\test10.jpg"
}
],
"paging": {
"nextUrl": "https://indesign-stage.adobe.io/v3/status/b50a4f99-4e80-4194-ac2a-043aaddae4ad?size=10&page=1"
}
}
- prevUrl: Present when a previous page exists.
- nextUrl: Present when a next page exists.
- If a direction is not applicable, its URL is omitted from the response.
Using webhooks
InDesign APIs events provide job processing details similar to those shown in the status calls of InDesign APIs. However, InDesign API events are more comprehensive.
Please refer to the InDesign APIs Webhooks for a detailed guide on setting up webhooks.
Validation workflow for adopting new App Version
New InDesign app version will be available in advance with preview status before becoming active and default so that users can validate their custom scripts before adopting the new app version. This workflow helps ensure that custom scripts continue to work correctly with the new app version.
step 1: Validate against new InDesign app version with x-app-version header
step 2: If Custom Script uses ALWAYS_LATEST Strategy
step 3: If Custom Script uses fixed_major_version or fixed_major_and_minor_version Strategy
Once validation is complete, update your production scripts to use the new app version.