DS Server

Web API

Topic

Two HTTP requests are all it takes to have DS Server convert a document: one for an access token, one for the conversion. The steps below send them with curl in a bash shell, convert an HTML document to PDF and save the result, and then repeat the same requests in JavaScript with Node.js. Whatever language your application is written in, the requests stay the same, so the commands also show what your own HTTP client has to send.

Prerequisites

  • A DS Server. Either a DS Server of your own that is installed and registered, as the Installation Guide and Licensing describe, or a trial token for the trial server https://trial.dsserver.io.
  • A security profile that allows the client credentials grant type. On your own server, create it in the admin portal and turn on Allow "Client Credentials" grant type, as Create a Security Profile shows. The trial profile allows it already.
  • A bash shell with curl, jq and GNU base64, as on Linux or in the Windows Subsystem for Linux. jq reads the JSON responses; base64 encodes and decodes the documents.

Set the Connection Details

Open a terminal and store the address of DS Server and the credentials of the security profile in shell variables, so that the following commands can use them:

DS_URL="http://localhost:5000"
CLIENT_ID="<client ID>"
CLIENT_SECRET="<client secret>"

Replace http://localhost:5000 with the address of your DS Server, or with https://trial.dsserver.io for a trial token, and the placeholders with the client ID and the client secret of the profile. Client IDs that the admin portal creates start with dsserver..

Request an Access Token

DS Server issues access tokens at the endpoint /oauth/token. With the client credentials grant type, you send the client ID and the client secret as an HTTP Basic Authorization header, which the --user option of curl creates, and the grant type as form data:

curl --request POST "$DS_URL/oauth/token" \
    --user "$CLIENT_ID:$CLIENT_SECRET" \
    --data-urlencode grant_type=client_credentials

DS Server answers with the access token:

{
  "access_token": "<access token>",
  "token_type": "Bearer",
  "expires_in": "3600"
}

The token is valid for 3,600 seconds, one hour. Send the request again with jq at the end to store the token in a variable:

ACCESS_TOKEN=$(curl --silent --request POST "$DS_URL/oauth/token" \
    --user "$CLIENT_ID:$CLIENT_SECRET" \
    --data-urlencode grant_type=client_credentials | jq -r .access_token)

The client ID and the client secret must be in the header. Sent only as the form fields client_id and client_secret, DS Server rejects the request with Missing authorization header.

Convert a Document to PDF

The endpoint POST /documentprocessing/document/convert takes a document as a Base64-encoded string in a JSON body and returns the converted document the same way. The format of the result is the query parameter returnFormat.

  1. Create the document to convert, a small HTML file:

    printf '<h1>Invoice 1001</h1>\n<p>Thank you for your order.</p>\n' > invoice.html
    
  2. Encode it as Base64 and put it in quotes, which makes it a JSON string, in the file request.json:

    printf '"%s"' "$(base64 -w 0 invoice.html)" > request.json
    
  3. Send it to DS Server with the access token in a Bearer header:

    curl --silent --request POST "$DS_URL/documentprocessing/document/convert?returnFormat=PDF" \
        --header "Authorization: Bearer $ACCESS_TOKEN" \
        --header "Content-Type: application/json" \
        --data @request.json \
        --output response.json \
        --write-out '%{http_code}\n'
    

    curl saves the response body in response.json and prints the status code, 200 when the conversion succeeded.

  4. Decode the Base64 string of the response into the PDF file:

    jq -r . response.json | base64 --decode > invoice.pdf
    

Open invoice.pdf in a PDF viewer: it shows the heading "Invoice 1001" and the line below it.

What the Requests Do

  • The token request posts grant_type=client_credentials as application/x-www-form-urlencoded data to /oauth/token. A JSON body is not accepted there.
  • The conversion request posts the document as a JSON string, such as "PGgxPkludm9pY2Ug...", and passes the access token as Authorization: Bearer <access token>. Instead of the header, you can append the token as the query parameter access_token.
  • The response is a JSON string again: the PDF encoded as Base64. jq -r . removes the quotes, and base64 --decode turns the string back into binary data.
  • returnFormat accepts PDF, PDFA, RTF, DOC, DOCX, HTML, TX and TXT; it defaults to PDF. The input can be RTF, DOC, DOCX, HTML, PDF or the TX Text Control format; Supported File Formats lists what the Core build on Linux supports.

To convert a Word document, encode it instead of invoice.html in step 2. base64 -w 0 works for binary files as well.

The Same Requests in JavaScript

Every language with an HTTP client sends the same two requests. The following script does it with the fetch function of Node.js 20 or later and needs no package. Save it as convert.mjs in the folder that holds invoice.html:

import { readFile, writeFile } from "node:fs/promises";

const dsUrl = "http://localhost:5000";
const clientId = "<client ID>";
const clientSecret = "<client secret>";

// Request an access token with the client credentials grant type
const tokenResponse = await fetch(`${dsUrl}/oauth/token`, {
  method: "POST",
  headers: {
    "Authorization": "Basic " + Buffer.from(`${clientId}:${clientSecret}`).toString("base64"),
    "Content-Type": "application/x-www-form-urlencoded"
  },
  body: "grant_type=client_credentials"
});
if (!tokenResponse.ok) throw new Error(await tokenResponse.text());
const { access_token } = await tokenResponse.json();

// Send the HTML document as a Base64-encoded JSON string
const html = await readFile("invoice.html");
const convertResponse = await fetch(`${dsUrl}/documentprocessing/document/convert?returnFormat=PDF`, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${access_token}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify(html.toString("base64"))
});
if (!convertResponse.ok) throw new Error(await convertResponse.text());

// The response is the PDF document as a Base64-encoded JSON string
const pdf = await convertResponse.json();
await writeFile("invoice.pdf", Buffer.from(pdf, "base64"));
console.log("Saved invoice.pdf");

Replace the service URL and the credentials, and run the script:

node convert.mjs

The script prints Saved invoice.pdf and writes the same PDF as the curl commands. Run it on a server, not in a browser page: the client secret must not reach the browser.

Troubleshooting

DS Server answers errors of the token request with status code 400 and a JSON body that names the error:

{
  "error": "unsupported_grant_type",
  "error_description": "This security profile does not allow the specified grant type. (client_credentials)"
}
ResponseCauseFix
400, unsupported_grant_typeThe security profile doesn't allow the client credentials grant typeTurn on Allow "Client Credentials" grant type in the profile
400, invalid_client, Invalid client ID. or Invalid client secret.The client ID or the client secret is wrongCopy both again from the profile in the admin portal
400, invalid_request, Missing authorization header.The credentials were sent as form fields onlySend them as a Basic header, --user in curl
401 with an empty bodyOAuth is enabled and the access token is missing, wrong or expired, or the security profile has expiredRequest a new token and send it as Authorization: Bearer <access token>
400, DS Server is not registered.DS Server has no license yetRegister the server, as Licensing describes
400, One or more validation errors occurred.The body is not a JSON string, for example {}Put the Base64 string in quotes, as step 2 does

When DS Server answers an error, response.json holds its message instead of a document, and base64 --decode reports invalid input. Look at the file with cat response.json.

Next Steps