Announcing the New Adobe Document Services REST APIs

We are happy to announce the launch of a completely newly architected set of REST APIs for Adobe Document Services. While we’ve had APIs for some time now (they’re the power behind our existing SDKs), these new APIS will be significantly simpler to use and make it easier for developers on platforms outside our supported SDKs to create solutions for power document management workflows. In this post, we’ll describe what’s new, how to make use of the new APIs, and where to get support.
What do you need to do now?
Absolutely nothing. If your integration is working fine then there is no need to change anything. Our SDKs have been updated to use the new REST endpoints and there is a defined period of support for previous versions, but you have one year to upgrade your SDKs so there is no rush.
If you do update your SDK, there are no changes required to your code. Functionality in terms of the SDK’s public interface has not changed. TLDR — if you aren’t interested in switching to the REST API you do not have to be concerned at all.
What’s New?
First and foremost, the new APIs provide a much simpler interface. We’ll document how to use them below, but know that it will be much easier for developers to build integrations using these new endpoints.
While that by itself is good, there’s another benefit of the new APIs. Now when you upload a document for processing, for example, a PDF that needs to be OCRed, you have access to that asset in our storage for up to twenty-four hours. This means multiple operations will be quicker since you only have to upload the document once. This will be especially beneficial to developers making use of our Document Generation API, as they can upload their Word template once, and then make multiple calls passing their JSON data. To be clear, this isn’t permanent storage, but for scenarios where multiple operations are fired at once, developers will see the benefits.
Getting Started
Developers interested in trying the APIs should begin with our documentation. These new API docs describe the various operations and define what’s expected for input and output. Let’s begin by talking about how the APIs work at a high level.
Before you begin using the APIs, you’ll need credentials. If you are an existing developer and have credentials, your existing credentials will work just fine.
Let’s start by describing how the APIs work at a high level.
- You begin by getting a JWT and then an access token. There are multiple ways of doing this and you’ll see one when we get to the Node.js example below. You can find further details on our Authentication page.
- To work with a document, you begin by asking for an upload URL. You tell the API, “I need to upload a document of media type so and so.” This call will you a URL.
- You then upload your URL to that URL.
- Next, you kick off a job. These jobs correspond to our various APIs. So for example, OCR, generating or exporting PDFs, document generation, PDF Extraction, and so forth.
- When a job is started, you will then have an endpoint to check the status. You need to check this endpoint to see when your job is done, or if it threw an error.
- When done, you’ll have a new URL for your result. You can download your data from that URL.
This is a high-level description of how the new REST APIs work, now let’s break it down into code. Our examples will be in Node.js, but any language can be used.
Step One — Getting the access token
For Node.js, getting a JWT and access token can be done quickly using the @adobe/jwt-auth
package. This package handles the entire process for you, letting you pass in your credentials and get the access token you'll need.
For our demo, we put all of our credentials into a .env
file. This lets you mimic setting up environment variables in a testing environment. Our .env
file looks like so:
When you get credentials for Adobe Document Services, they are provided in two files, a JSON file, and a private.key
file. All we've done here is copied over the values from the JSON file and taken the private.key
contents and pasted them end. There is one small tweak necessary here, and that's converting the key contents into one line with line breaks (\n
). One way of doing that would be to write a quick script like so:
With our .env
file complete, we can then read the values in a script like so:
The @adobe\jwt-awt
package has one main method, auth(credentials)
. We can wrap this in a utility function to make it easier to use:
Step Two — Generating an upload URL
Before we can upload an asset, we need an upload URL. Doing this requires using the /assets
endpoint. This takes one argument, the media type. For our sample, we'll be doing an OCR operation so our media type is application/pdf
. Once again, we can abstract this into a function:
Our endpoints require two sets of credential information, the client id value and the access token generated earlier. You’ll see this repeated throughout this tutorial. The result of this call will be an object with an assetID
value and uploadUri
, the location we can upload our file. With this function written, we can call it like so:
Step Three — Upload the asset
The next step is the simplest — uploading the file. Here’s the utility function to handle that:
As the code admits, the error handling could be handled a bit better, but using the function is as simple as this:
Step Four — Create the Job
So far, everything we’ve done has been mostly “operation” agnostic, by that I mean, outside of selecting what file to upload, nothing has been specific to a particular operation. At this point, we need to fire off the job. As mentioned above, we’re doing an OCR operation. You can find the docs for that endpoint here: https://developer.adobe.com/document-services/docs/apis/#tag/OCR

Looking at the docs, we see we need to hit /operation/ocr
and pass in the asset ID of our file. We can also pass in a language and type, but these values are optional.
All operations, when done, return a location that can be polled for status. Here’s a utility function that wraps the OCR endpoint, but note that it doesn’t support the optional parameters.
Notice that the client ID and access token are required again. Here’s a sample call to this function:
Step Five — Poll for Completion
This next step is a bit complex. Checking job status by itself is simple. You take the URL from the previous step and just hit it. The result will be an object containing the current status. While it’s working, you’ll get “in progress”. If something went wrong, you’ll get “failed”. When complete, you get a value of “done” along with an asset
value that includes the type and size of the result as well as a downloadUri
value.
The complexity comes into how you handle checking the job over time. For the sample solution provided here, we used a loop with a delay. This could be done a bit better, but it’s a simple enough solution. First, here’s a delay
function used to pause execution for a certain number of milliseconds:
And then here’s the pollJob
function that makes use of it. As stated above, error handling definitely needs to be improved.
Calling it looks like so:
Step Six — Download the asset
Once the job successfully completes, the last step is to download the result. While a utility function isn’t really necessary for such a quick task, here’s one we built to make it easier:
Calling it requires the URL from the previous polling operation and a place to store the file:
Here’s the entire application. You can also grab a copy of it here: https://github.com/cfjedimaster/document-services-demos/blob/main/rest/test1.js
Next steps
Want to give this a spin? Head over to our docs today and give it a try. If you need help, be sure to reach out on our forums and ask away!