Skip to main content

Upload

The configuration is located in /upload/config.ion.

The configuration file itself is optional.

All properties in the configuration file are also optional.

Project config files inherit properties from tenant config files which inherit from the global defaults as given below.

See URL Connections for detailed description of the connection configuration.

Matching Connections to URLs

The upload worker will send HTTP requests to notify success of priint cloud rendering jobs.

The project configuration contains a list of connection configurations identified by their url property. Typically, just one.

The best matching configuration is the configuration with the longest matching URL part (computed from the start of the URL).

If no matching configuration is found the system falls back to a default configuration.

Typical Project Configuration Example

// /tenants/example.com/projects/datasheets/upload/config.ion
{
"connections": [{
"method": "POST",
"url": "https://example.com/priint-artifacts",
"authentication": {
"type": "ApiKey",
"key": "API-KEY",
"value": "8e104bcc93c9f7af5626bbfae2c0295eced7d86985b90f639e8844"
},
"use-chunked-transfer": false
}]
}

Together with a uploadUrl setting of https://example.com/priint-artifacts/{ticket} in /restapi/config.ion this configuration will lead to an HTTP Request like this:

POST /priint-artifacts/u6g3fzzv36nzswjdb6dzdiuvpy HTTP/1.1
Host: https://example.com
API-KEY: 8e104bcc93c9f7af5626bbfae2c0295eced7d86985b90f639e8844
Content-type: application/octet-stream
User-agent: priintgrid-upload
Content-Length: 456788

<Binary-PDF-Data>

There are three differences here compared to the default behavior:

  • the HTTP method (POST instead of PUT)
  • the API Key authentication
  • the default transfer-encoding (no chunked but in one block with content-length)

Default Behavior

If upload worker does only find a whitelisted URL in the config, then the system falls back to a default request.

Given the hypothetical renderpdf request like

POST /tenants/example.com/projects/datasheets/renderpdf
?custom=foo:bar
&foreignKey=0815
&upload=https://example.com/priint-artifacts/%7Bticket%7D

and a user "datasheet-jobs" job ticket of "u6g3fzzv36nzswjdb6dzdiuvpy"

and a very simple configuration like

// /tenants/example.com/projects/datasheets/upload/config.ion
{
"connections": [{
"url": "https://example.com/"
}]}

we get the following request to the upload URL:

PUT /priint-artifacts/u6g3fzzv36nzswjdb6dzdiuvpy HTTP/1.1
Host: https://example.com
Content-type: application/json
User-agent: priintgrid-upload
Transfer-Encoding: chunked

<Binary-PDF-Data>

Response Evaluation and Parameter Export

The response of an upload is normally only checked for success (HTTP status 2xx).

In some cases, values must be extracted from a response header or body to be fed into later callback requests. This is typically a media ID generated by the server side during upload.

Responses can be evaluated and values extracted into "export parameter" strings.

The following configuration example shows all three possible types of parameter extraction (header, JSON body, XML body). Typically, you will find only one or none at all (and never will XML and JSON be mixed, of course).

// /tenants/example.com/projects/datasheets/upload/config.ion
{
"connections": [{
"url": "https://example.com/",
"exportParams": [
{
"name": "myparam1",
"path": "MY_COSTUM_HEADER_NAME",
"source": "headers"
},
{
"name": "myparam2",
"source": "jsonBody",
"path": "my/jxpath/expr"
},
{
"name": "myparam3",
"source": "xmlBody",
"path": "my/xpath/expr"
}
]
}]
}

Possible Sources

  • headers
    • "headers" is the default source type (so it can be omitted)
    • path contains the plain name (case-insensitive) of an HTTP response header
    • path may alternatively contain an XPath 1.0 expression to evaluate a map of key-value pairs (keys in lowercase only) (using JXPath library)
  • jsonBody
    • response body is parsed as JSON (if possible)
    • path specifies an XPath 1.0 expression to evaluate the JSON object map or array (using JXPath library)
  • xmlBody
    • response body is parsed into an XML document (if possible)
    • path specifies an XPath 1.0 expression to evaluate the XML object map or array (using standard JAXP). The context starts with the XML document element.

JSON

{
"my": {
"jxpath": {
"expr": [
"abc",
123
]
}
}
}

The above expression my/jxpath/expr will return the string abc. To get the second expression you will use my/jxpath/expr[2].

XML

<root>
<my>
<xpath>
<expr>abc</expr>
<expr>123</expr>
</xpath>
</my>
</root>

The above expression my/xpath/expr will return the first expr string abc. To get the second expression you will use my/xpath/expr[2].

Custom Uploader

Currently, only Bynder DAM is supported.

Bynder DAM Integration

Configuration Example:

Client Credentials
// /tenants/example.com/projects/datasheets/upload/config.ion
{
"connections": [
{
"url": "https://bynder.example.com",
"uploadType": "bynder",
"authentication": {
"type": "OAuth2",
"grantType": "ClientCredentials",
"clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"clientSecret": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
}
}
]
}

It is recommended to seal the value of the clientSecret so that it looks like

"clientSecret": "{sealed:1:xxx:xxx:xxxxxxxxxxxxxxxxxxxxxxxx}"

Authorization Code + Refresh Token

(Internal Use Only — Not Recommended)

⚠️ Warning
The Authorization Code flow is designed for human user delegation and requires an interactive redirect. It is not suitable for our headless service, which aligns with the Client Credentials grant type for technical integrations. Use this flow only for internal testing or exceptional cases.

If you have an authorization code and refresh token from Bynder’s OAuth2 Authorization Code flow, configure as follows:

// /tenants/example.com/projects/datasheets/upload/config.ion
{
"connections": [
{
"url": "https://bynder.example.com",
"uploadType": "bynder",
"authentication": {
"type": "OAuth2",
"grantType": "AuthorizationCode",
"clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"clientSecret": "{sealed:1:xxx:xxx:xxxxxxxxxxxxxxxxxxxxxxxx}",
"codeVerifier": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"redirectUri": "https://your-app.example.com/callback",
"params": {
"bynder_refresh_token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
}
}
}
]
}

Notes:

  • No server-side redirect: The service cannot handle interactive redirects. Obtain the authorization code and refresh token externally (e.g., via browser or OAuth2 client tool) and add them to the configuration.
  • Refresh token scope: Include the offline scope in the authorization request to obtain a non-expiring refresh token for new access tokens without user interaction.
  • Preferred method: Use Client Credentials for technical integrations, as it is the supported flow for this service.

Scope

The default scope is as follows:

  • offline
  • asset:read
  • asset:write
  • collection:read
  • collection:write
  • meta.assetbank:read
  • meta.assetbank:write

Users may want to override this setting by explicitly setting the authentication.scope for the connection. Scope is a comma separated string.

     "authentication" : {
"type": "OAuth2",
"scope": "asset:read,asset:write"
// ... other settings ...
}

Supported Custom Parameters

API users can set some custom parameters when starting a rendering.

The following custom parameters are supported to control the Bynder upload:

NameDescription
bynder_asset_nameSets a custom asset_name. The default is priint-<ticket>.
bynder_media_idSets a fixed media_id for Bynder upload (not recommended)
bynder_tagsComma separated list of Bynder tag IDs
bynder_meta_propsComma separated list of meta property names
bynder_meta_key_<prop>Property key id for the property prop as declared in bynder_meta_props
bynder_meta_val_<prop>Property value id for the property prop as declared in bynder_meta_props
Examples:

Setting asset name.

/rest/tenants/example.com/projects/datasheets/renderpdf?custom=bynder_asset_name:foo-bar`

Setting custom metaproperty

/rest/tenants/example.com/projects/datasheets/renderpdf \
?custom=bynder_meta_props:myprop \
&custom=bynder_meta_key_myprop:85eaeca7-6cab-407d-8f27-0bdeb9039daf \
&custom=bynder_meta_val_myprop:1bd9e59d-5d35-4c7b-889a-8c46238229b1

Bynder Media Object

Content of Bynder Media after upload looks as follows (just if you were wondering):

media 
archive = false
brandId = "9EEC65CC-E8D6-40D9-5FAF4F1DC5971741"
copyright = ""
customMetaproperties = {}
dateCreated = "2026-05-04T03:02:001Z"
dateModified = "2026-05-04T03:02:001Z"
datePublished = "2026-05-04T03:02:001Z"
description = ""
extensions = []]
fileSize = 4
focusPoint = {}
height = 0
id = "27347D33-2F9C-CB45-930F1AF4B1F008FC"
isLimited = false
isPublic = false
mediaItems = null
name = "priint-pm3m5dm3tcijdgvvrgrqtuj4rq"
orientation = ""
original = "https://bynder.example.com/m/69a98dc1add6c4a9/original/priint-pm3m5dm3tcijdgvvrgrqtuj4rq.pdf"
propertyOptions = []
tags = null
thumbnails = []
type = "document"
videoPreviewURLs = null
width = 0