Introduction
Welcome to the Artwork API, a powerful tool that allows you to seamlessly integrate artworker.io into your workflow. With this API, you can create, update and attach artwork to artworker jobs.
You can view code examples in the dark area to the right.
Authentication
To authorize, use the
api_key
query param:POST https://open-api.artworker.io/v1/route ?api_key=[API_KEY]
Make sure to replace
[API_KEY]
with your API key.
Artworker uses API keys to allow access to the API. You can register a new Artworker API key at our developer portal.
Artworker expects the API key to be included in all API requests to the server as a query parameter that looks like the following:
?api_key=[API_KEY]
Jobs
Job Object
Sample Job Object
{
"id": "63e6357ad9a28b28ab9",
"ref": "ODR1382",
"name": "Flyers",
"state": "created",
"customerActionURL": "",
"supplerActionURL": "https://app.artworker.io/artwork/63e6357ad9a28b28ab9",
}
Field | Description |
---|---|
job.id | The id of the job. |
job.name | The jobs name. |
job.ref | The jobs reference. |
job.state | The state of the current job. |
job.customerActionURL | URL for the customer to visit to perform any required action. Returns an empty string if no action required. |
job.supplerActionURL | URL for the supplier to visit to perform any required action. Returns an empty string if no action required. |
Job States
awaiting_artwork
Job ready to recieve artwork
rejected
Artwork rejected by admin, waiting for customer to review
pending_approval
Artwork uploaded by customer or admin and awaiting review
ready_for_production
Artwork approved and ready for production
pending_proof_approval
Proof(s) sent to customer for approval
proof_rejected
Customer has rejected proof(s)
proof_accepted
Customer has accepted proof(s)
complete
Job marked as complete by admin
Create a Job
POST https://open-api.artworker.io /v1/job ?api_key=[API_KEY]
Headers
Content-Type: application/json
Sample Body
{
"customerEmail": "[email protected]",
"customerName": "John Doe",
"jobName": "Flyers",
"jobRef": "ODR1382",
"mediaUrls": [
"https://storage.cloud.google.com/artworker-api-docs/samples/model-3-leaflet.pdf"
]
}
Sample Response
{
"job": {
"id": "63e6357ad9a28b28ab9",
"ref": "ODR1382",
"name": "Flyers",
"state": "created",
"customerActionURL": "",
"supplerActionURL": "https://app.artworker.io/artwork/63e6357ad9a28b28ab9",
}
}
This endpoint creates a new job within artworker.
HTTP Request
POST https://open-api.artworker.io/v1/job?api_key=[API_KEY]
Body Parameters
Parameter | Required | Description |
---|---|---|
customerEmail | true | The customers email address. |
customerName | true | The customers name. |
jobName | true | A name for the job. This should (although does not have to be) be unique to prevent multiple jobs with the same name within artworker. |
jobRef | false | A reference for the name, not used by our system but useful if you want to associate the job with an order number for example. |
mediaUrls | false | URLs to artwork files to be imported into artworker and attached to this job. Must be publically accessible. |
Response
Parameter | Description |
---|---|
job.id | The id of the job. |
job.name | The jobs name. |
job.ref | The jobs reference. |
job.state | The state of the current job. |
job.customerActionURL | URL for the customer to visit to perform any required action. Returns an empty string if no action required. |
job.supplerActionURL | URL for the supplier to visit to perform any required action. Returns an empty string if no action required. |
Webhook_Endpoint
Webhook Endpoints
POST /v1/webhook_endpoint
GET /v1/webhook_endpoint/:id
POST /v1/webhook_endpoint/:id
GET /v1/webhook_endpoint
DELETE /v1/webhook_endpoint/:id
You can configure webhook endpoints via the API to be notified about events that happen in your Stripe account or connected accounts.
Most users configure webhooks from the dashboard, which provides a user interface for registering and testing your webhook endpoints.
Webhook Object
Sample Webhook Object
{
"webhook": {
"id": 1234,
"url": "https://dev.example.com/api/webhook",
"secret": "whsec_85n9845yt754n87y35",
"enabledEvents": ["job.complete"]
}
}
Field | Description |
---|---|
id | Unique identifier for the object. |
url | The URL of the webhook endpoint. |
secret | The endpoint’s secret, used to generate webhook signatures. |
enabledEvents | List of enabled events for this endpoint |
Create a Webhook
POST https://open-api.artworker.io /v1/webhook_endpoint ?api_key=[API_KEY]
Headers
Content-Type: application/json
Sample Body
{
"url": "https://dev.example.com/api/webhook",
"enabledEvents": ["job.complete"]
}
Sample Response
{
"webhook": WebhookObject
}
A webhook endpoint must have a url and a list of enabled_events. You can also create webhook endpoints in the webhooks section of the Settings page.
HTTP Request
POST https://open-api.artworker.io/v1/webhook_endpoint?api_key=[API_KEY]
Body Parameters
Parameter | Required | Description |
---|---|---|
url | true | The URL of the webhook endpoint. |
enabledEvents | true | The list of events to enable for this endpoint. |
Response Body
Field | Description |
---|---|
webhook | WebhookObject |
Get a Webhook
GET https://open-api.artworker.io /v1/webhook_endpoint/1234 ?api_key=[API_KEY]
Headers
Content-Type: application/json
Sample Response
{
"webhook": WebhookObject
}
This endpoint gets a single webhook by id.
HTTP Request
GET https://open-api.artworker.io/v1/webhook_endpoint/:id?api_key=[API_KEY]
Response Body
Field | Description |
---|---|
webhook | WebhookObject |
Update a Webhook
POST https://open-api.artworker.io /v1/webhook_endpoint/1234 ?api_key=[API_KEY]
Headers
Content-Type: application/json
Sample Body
{
"webhook": WebhookObject
}
Sample Response
{
"webhook": WebhookObject
}
This endpoint updates a webhook within artworker.
HTTP Request
POST https://open-api.artworker.io/v1/webhook_endpoint/:id?api_key=[API_KEY]
Body Parameters
Parameter | Required | Description |
---|---|---|
webhook | WebhookObject |
Response Body
Field | Description |
---|---|
webhook | WebhookObject |
List Webhooks
GET https://open-api.artworker.io /v1/webhook_endpoint/1234 ?api_key=[API_KEY]
Headers
Content-Type: application/json
Sample Response
{
"webhooks": WebhookObject[]
}
This endpoint lists all the artworker accounts webhooks. There is a limit of 5 webhooks per account, so the max length of the returned array is 5.
HTTP Request
GET https://open-api.artworker.io/v1/webhook_endpoint?api_key=[API_KEY]
Response Body
Field | Description |
---|---|
webhooks | WebhookObject[] |
Delete a Webhook
DELETE https://open-api.artworker.io /v1/webhook_endpoint/1234 ?api_key=[API_KEY]
Headers
Content-Type: application/json
Sample Response
{
"ok": true
}
This endpoint deletes a webhook by id.
HTTP Request
DELETE https://open-api.artworker.io/v1/webhook_endpoint/:id?api_key=[API_KEY]
Response Body
Field | Description |
---|---|
ok | returns true if successfully deleted |
Errors
The Artworker API uses the following error codes:
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request is invalid. |
401 | Unauthorized -- Your API key is wrong. |
404 | Not Found -- The specified object could not be found. |
405 | Method Not Allowed -- You tried to access an invalid method. |
406 | Not Acceptable -- You requested a format that isn't json. |
410 | Gone -- The object requested has been removed from our servers. |
418 | I'm a teapot. |
429 | Too Many Requests -- You've reached the limit! Slow down! |
500 | Internal Server Error -- We had a problem with our server. Try again later. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |
Webhooks
Use incoming webhooks to get real-time updates
Listen for events on your Artworker account so your integration can automatically trigger reactions. Artworker uses webhooks to notify your application when an event happens in your account.
How Artworker uses webhooks
A webhook enables Artworker to push real-time notifications to your app. Artworker uses HTTPS to send these notifications to your app as a JSON payload. You can then use these notifications to execute actions in your backend systems.
Webhook Events
When an event occurs, we create a new Webhook Event Object object. If you registered a webhook endpoint to receive that event, we send it to your endpoint as part of a POST request.
Webhook Event Object
Sample Body
{
"eventId": "29fdefd3-f499-49a5-8dae-db53b4321d41",
"event": "job.complete",
"createdAt": "2023-02-10T09:15:09.7345339Z",
"data": {
"id": "43991f5c-f75a-459d-9fd2-decaca579354",
"name": "flyers",
"ref": "order001",
"state": "complete",
"customerActionURL": "",
"supplerActionURL": ""
}
}
Parameter | Description |
---|---|
eventID | ID of the event. |
event | Webhook Events. |
createdAt | timestamp |
data | Job |
Webhook Events
job.awaiting_artwork
Occurs when an admin sends an artwork request to a customer.
job.rejected
Occurs when an admin reject one of more files in a job.
job.pending_approval
Occurs when artwork has been uploaded either by the customer, or by the supplier and is ready for review.
job.ready_for_production
Occurs either when an admin has approved all artwork for a job, or when a customer has accepted provided fixup files or accepted highlighted issues.
job.pending_proof_approval
Occurs when an admin sends proof(s) to the customer
job.proof_rejected
Occurs when a customer rejects one or more proofs in a job
job.proof_accepted
Occurs when a customer approved all proofs in a job
job.complete
Occurs when an admin marks a job as complete
Steps to receive webhooks
- Identify the events you want to monitor, and the event payloads to parse.
- Create a webhook endpoint as an HTTP endpoint on your local server.
- Handle requests from Artworker by parsing each event object and returning
200
or201
response status codes - Test your webhook endpoint is working properly with ngrok
- Deploy your webhook endpoint so it's publicly accessible HTTPS URL
- Register your publicly accessible HTTPS URL in your Artworker account settings.
1: Identify the events to monitor
Use the list of events above (Webhook Events) to identify which events you want to recieve notification of and take a note of the event object payload.
2: Setting up locally
To get up and running locally, you will need
- A local application serving an endpoint like
http://localhost:8080/artworker_webhooks
- To make this endpoint accessible to the internet
Route setup
const http = require('http');
const server = http.createServer((req, res) => {
if (req.method === 'POST' && req.url === '/artworker_webhooks') {
let body = '';
req.on('data', chunk => { body += chunk.toString(); });
req.on('end', () => {
console.log(body);
res.end('Event received');
});
} else {
res.statusCode = 404;
res.end('Not Found');
}
});
server.listen(8080, () => {
console.log('Server listening on http://localhost:8080');
});
Set up an HTTP endpoint on your local machine that can accept unauthenticated webhook requests with a POST method.
For a quick start, the code on the right is a small node app that starts a server on 8080 and accepts
unauthenticated POST requests to http://localhost:8080/artworker_webhooks
Ngrok setup
Artworker cannot send events directly to your local system as the endpoint is not accessible to the internet. To change that ngrok can be used to route requests through a hosted endpoint to your local one. Once ngrok is installed from https://ngrok.com/, run the following command and make a note of the endpoint it outputs.
ngrok http 8080
Artworker setup
In the Artworker settings page, navigate to webhooks and create a new one with your ngrok url (dont forget to
all the /artworker_webhooks
to the end!) eg
https://337f-86-175-154-122.ngrok.io/artworker_webhooks
with the desired events.
Create a couple of test jobs and you should start to see events hitting the endpoint!
3: Handle events from Artworker
Check event objects
Each event is structured as an Webhook Event Object object with a event, eventId, and related Artworker resource nested under data. Your endpoint must check the event type and parse the payload of each event.
Return a 2xx response
Your endpoint should return a positive status code (2xx) quickly before executing any complicated procedures that might result in a timeout.
Built-in retries
Artworker's webhooks come equipped with automatic retry mechanisms for response status codes 3xx, 4xx, or 5xx. Artworker stop trying to deliver the request after 2 days.
4: Secure your webhooks (recommended)
Artworker has the option to authenticate the webhook events it sends to your endpoints by including a signature in the Artworker-Signature header of each event. This ensures that the events were sent by Artworker and not by an unauthorized third party.
To verify the signatures, you must first retrieve the secret for your endpoint from the Webhooks settings.
It's important to note that Artworker generates a unique secret key for each endpoint. If you have multiple endpoints, you will need to retrieve the secret for each one you want to verify signatures on.
Verifying signatures
Artworker-Signature:
t=1492774577,
v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
The Artworker-Signature header included in each signed event contains a timestamp and one signature. The
timestamp is prefixed by t=
and the signature by v1=
const artworkersig = req.headers['artworker-signature'];
let [timestamp, sig] = artworkersig.split(",")
timestamp = timestamp.replace("t=", "")
sig = sig.replace("v1=", "")
const stripeSecret = crypto.createHmac('sha256', STRIPE_SIGNING_SECRET)
.update(`${timestamp}.${body}`)
.digest('hex');
const verified = stripeSecret === sig
Artworker generates signatures using a hash-based message authentication code (HMAC) with SHA-256
Step 1: Extract the timestamp and signatures from the heade
Split the header, using the , character as the separator, to get a list of elements. Then split each element, using the = character as the separator, to get a prefix and value pair.
The value for the prefix t corresponds to the timestamp, and v1 corresponds to the signature (or signatures). You can discard all other elements.
Step 2: Prepare the signed_payload string
The signed_payload string is created by concatenating:
The timestamp (as a string) The character . The actual JSON payload (that is, the request body) Step 3: Determine the expected signature Compute an HMAC with the SHA256 hash function. Use the endpoint’s signing secret as the key, and use the signed_payload string as the message.
Step 4: Compare the signatures
Compare the signature (or signatures) in the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.
To protect against timing attacks, use a constant-time string comparison to compare the expected signature to each of the received signatures.
Preventing replay attacks
A replay attack occurs when a malicious party captures a legitimate payload and its accompanying signature and sends them again. To prevent such attacks, Artworker includes a timestamp in the Artworker-Signature header. This timestamp is part of the signed payload and is verified by the signature, making it impossible for the attacker to alter the timestamp without altering the signature. If the signature is still valid but the timestamp is outdated, your application can choose to reject the payload.
Artworker creates a new timestamp and signature each time it sends an event to your endpoint. In cases where Artworker retries sending an event (e.g., if your endpoint responded with a non-2xx status code on the previous attempt), a fresh signature and timestamp will be generated for the new delivery attempt.
PDF_Profile_Job
PDF Profile Job Endpoints
POST /v1/pdf-profile/job
GET /v1/pdf-profile/job/custom-uid/:custom-uid
You can submit a PDF to apply a predefined Callas profile, and generate new output PDFs. The job runs asynchronously, and users can poll a "profileJob" object to track the status.
PDF Profile Job Object
Sample PDF Profile Job Object
{
"pdfProfileJob": {
"createdAt": "2024-09-04T10:10:10Z",
"updatedAt": "2024-09-04T10:15:15Z",
"customUid": "unique-custom-uid-5-6",
"state": "processing",
"originalFilename": "model-3-leaflets-proofs.pdf",
"originalUrl": "https://storage.googleapis.com/sample.pdf",
"originalThumbnailUrl": "https://storage.googleapis.com/sample-thumbnail.jpg",
"outputFiles": [
{
"url": "https://storage.googleapis.com/output1.pdf",
"originalFilename": "output1.pdf",
"thumbnailUrl": "https://storage.googleapis.com/output1-thumbnail.jpg"
}
],
"hasErrors": false,
"timeline": [
{
"createdAt": "2024-09-04T10:11:00Z",
"updatedAt": "2024-09-04T10:13:00Z",
"action": "profile_applied",
"error": ""
}
],
"profileName": "default",
"configOptions": {}
}
}
Field | Description |
---|---|
createdAt | The timestamp when the job was created. |
updatedAt | The timestamp when the job was last updated. |
customUid | A custom identifier provided by the user. |
state | The current state of the job. |
originalFilename | The original filename of the uploaded PDF. |
originalUrl | The URL of the original PDF file. |
originalThumbnailUrl | The URL of the thumbnail image of the original PDF. |
outputFiles | An array of output files generated by the profile. Each item in the array contains: - url : The URL to access the output PDF file. - originalFilename : The
filename of the output PDF. - thumbnailUrl : The URL to access a thumbnail of the output
PDF. |
hasErrors | A boolean indicating if the job encountered errors. |
timeline | An array representing the history of actions performed on the job. Each item in the array contains: - createdAt : The timestamp when the action occurred. - updatedAt : The
timestamp when the action was updated. - action : The action performed on the job (e.g.,
profile_applied). - error : Details of any error encountered during the action (if
applicable). |
profileName | The name of the profile applied to the PDF. |
configOptions | Configuration options specific to the profile applied. |
Profile Job States
PdfProfileJobStateUndefined
The job state is undefined. This typically indicates that the job has not yet been initialized or there is an issue with the job status.
PdfProfileJobStateImporting
The job is in the process of importing the PDF from the provided URL. This state covers downloading and preparing the PDF for processing.
PdfProfileJobStateQueued
The job has been queued for processing. It is waiting for available resources or a turn in the processing pipeline.
PdfProfileJobStateProcessing
The job is actively being processed. The profile is being applied to the PDF, and output files are being generated.
PdfProfileJobStateDone
The job has completed successfully. The processed PDF(s) and any related output files are available for download.
PdfProfileJobStateError
The job encountered an error during processing. The error details can be found in the timeline
error
fields, and no valid output files were generated.
Create a PDF Profile Job
POST https://open-api.artworker.io /v1/pdf-profile/job ?api_key=[API_KEY]
Headers
Content-Type: application/json
Sample Body
{
"profileName": "default",
"url": "https://storage.googleapis.com/assets-store/model-3-leaflets-proofs.pdf",
"configOptions": {},
"customUid": "unique-custom-uid-5-6",
"outputBasename": "base123",
"outputFilenames": ["file1.pdf", "file2.pdf"]
}
Sample Response
{
"pdfProfileJob": {
"createdAt": "2024-09-04T10:10:10Z",
"updatedAt": "2024-09-04T10:15:15Z",
"customUid": "unique-custom-uid",
"state": "PdfProfileJobStateImporting",
"originalFilename": "model-3-leaflets-proofs.pdf",
"originalUrl": "https://storage.googleapis.com/kudo-assets-store/model-3-leaflets-proofs.pdf",
"originalThumbnailUrl": "https://storage.googleapis.com/sample-thumbnail.jpg",
"outputFiles": [],
"hasErrors": false,
"timeline": [],
"profileName": "default",
"configOptions": {}
}
}
This endpoint initiates the PDF profiling job. The job applies a specified Callas profile to a PDF, provided via a URL, and returns a job object for tracking.
HTTP Request
POST https://open-api.artworker.io/v1/pdf-profile/job?api_key=[API_KEY]
Body Parameters
Parameter | Required | Description |
---|---|---|
profileName | true | The name of the Callas profile to apply to the PDF. |
url | true | The URL of the PDF to apply the profile to. |
configOptions | false | Configuration options specific to the chosen profile. |
customUid | false | A user-provided unique identifier for tracking the job. |
outputBasename | false | Basename for output files. Example - 'basefilename' will output "basefilename_0001.pdf" and "basefilename_0002.pdf" if 2 output files are generated. |
outputFilenames | false | Array of output file names for each output file. Requires outputBasename to be set as a fallback. |
Response Body
Field | Description |
---|---|
pdfProfileJob | PDF Profile Job Object |
Get a PDF Profile Job by custom-uid
GET https://open-api.artworker.io /v1/pdf-profile/job/custom-uid/:custom-uid ?api_key=[API_KEY]&expand=timeline
Headers
Content-Type: application/json
Sample Response
{
"pdfProfileJob": {
"createdAt": "2024-09-04T10:10:10Z",
"updatedAt": "2024-09-04T10:15:15Z",
"customUid": "unique-custom-uid-5-6",
"state": "PdfProfileJobStateDone",
"originalFilename": "model-3-leaflets-proofs.pdf",
"originalUrl": "https://storage.googleapis.com/sample.pdf",
"originalThumbnailUrl": "https://storage.googleapis.com/sample-thumbnail.jpg",
"outputFiles": [
{
"url": "https://storage.googleapis.com/output1.pdf",
"originalFilename": "output1.pdf",
"thumbnailUrl": "https://storage.googleapis.com/output1-thumbnail.jpg"
}
],
"hasErrors": false,
"timeline": [
{
"createdAt": "2024-09-04T10:10:10Z",
"updatedAt": "2024-09-04T10:10:10Z",
"action": "PdfProfileJobActionImported",
"error": ""
},
{
"createdAt": "2024-09-04T10:10:10Z",
"updatedAt": "2024-09-04T10:10:10Z",
"action": "PdfProfileJobActionStartProcessing",
"error": ""
},
{
"createdAt": "2024-09-04T10:10:10Z",
"updatedAt": "2024-09-04T10:10:10Z",
"action": "PdfProfileJobActionDone",
"error": ""
}
],
"profileName": "default",
"configOptions": {}
}
}
This endpoint retrieves the status and details of a specific PDF profile job by its custom-uid.
HTTP Request
GET https://open-api.artworker.io/v1/pdf-profile/job/:id?api_key=[API_KEY]
Query Parameters
Parameter | Description |
---|---|
?expand=timeline | populates the timeline array |
Response Body
Field | Description |
---|---|
pdfProfileJob | PDF Profile Job Object |
Task API
Workflows & Tasks
Processing files is done via workflows in the terminology of the Artworker REST API. Each workflow consists of one or more tasks.
For example: The first task of a workflow could be importing the file(s) from a specific source. The second task could be running a preflight process on the file(s).
It is possible to chain tasks and pass the output of one task to the next. This is useful if you want to add bleed and create a thumbnail or preview with the added bleed, for example.
Import Tasks
An import task is a task that imports one or multiple files into Artworker for use in other tasks. Examples of import tasks include downloading files from a URL. Imported files are only stored temporarily.
Typically, each workflow has at least one import task.
Errors and Rate Limiting
The Artworker API responds with standard HTTP status codes, such as 400 (invalid data), 500 (internal server error), 503 (temporarily unavailable), or 429 (too many requests).
Rate Limiting
Some endpoints enforce dynamic rate limiting. These endpoints return the X-RateLimit-Limit
and
X-RateLimit-Remaining
headers. If the limit is reached, a 429 error is returned along with a
Retry-After
header that specifies the time in seconds to wait before making the next request.
Endpoints Currently Rate Limited:
- Creating workflows
Failed Workflows and Tasks
Workflows and tasks that complete with an error will have their status set to error
. More about
the error can be found in the error
within each task, system errors are listed below. In addition
to these check the task documentation for Task specific errors.
Error Code | Description |
---|---|
0 | Unknown system error. |
1 | A generic server error occurred. |
2 | The server is currently unavailable. |
3 | The request was malformed or invalid. |
4 | The server received an invalid response from the upstream server. |
5 | The gateway is currently unavailable. |
30 | The network request timed out. |
Please do not automatically retry tasks. Artworker internally already retries tasks if there are retryable errors (such as network errors).
Create Workflows
POST https://open-api.artworker.io /v1/taskapi/workflows?api_key=[API_KEY]
Sample Body
{
"uuid": "myworkflow-123",
"tasks": {
"import": {
"operation": "import/URL",
"payload": {
"urls": ["https://storage.googleapis.com/kudo-web-assets/upload-examples/example_five.pdf"]
}
},
"fixup": {
"operation": "run/pdf-advanced-edit",
"input": "import",
"payload": {
"pageRange": "1",
"options":{
"removePrinterMarks": {
"enabled": true
}
}
}
}
}
}
Create a workflow with one ore more tasks. This endpoint is asynchronous and responds immediately
Parameter | Type | Required | Description |
---|---|---|---|
tasks | array [task] | true | The example consists of two tasks: import-my-file and preflight-my-file . You
can name these tasks however you want, but only alphanumeric characters, - , and
_ are allowed in the task names. Each task has an operation (for example:
import/url or preflight ). The input parameter allows it to directly
reference the name of another task created within the same workflow request. If a task changes the PDF in
some way (e.g., adds bleed), then it will output a new PDF; a task with a specified input
will use the output of the previous task. This allows you to chain tasks together and create a workflow
for your files. |
uuid | string | false | A string to identify the workflow, used for associating it with an ID in your application without affecting functionality. |
Get a Workflow
GET https://open-api.artworker.io /v1/taskapi/workflows/100?api_key=[API_KEY]
Sample Response
{
"id": 100,
"uuid": "myworkflow-123",
"status": "completed",
"createdAt": "2024-12-18T11:00:03.721923Z",
"endedAt": "2024-12-18T11:00:06.642034Z",
"tasks": [
{
"id": 200,
"operation": "import/URL",
"name": "import",
"payload": {
"urls": [
"https://storage.googleapis.com/kudo-web-assets/upload-examples/example_five.pdf"
]
},
"status": "completed",
"error": null,
"createdAt": "2024-12-18T11:00:03.725411Z",
"startedAt": "2024-12-18T11:00:03.725411Z",
"endedAt": "2024-12-18T11:00:03.811505Z",
"links": {
"self": "https://open-api.artworker.io/workflow/100/task/import"
}
},
{
"id": 201,
"operation": "run/pdf-advanced-edit",
"name": "fixup",
"dependsOn": "import",
"payload": {
"options": {
"removePrinterMarks": {
"enabled": true
}
},
"pageRange": "1"
},
"status": "completed",
"error": null,
"createdAt": "2024-12-18T11:00:03.725411Z",
"startedAt": "2024-12-18T11:00:03.725411Z",
"endedAt": "2024-12-18T11:00:03.811505Z",
"links": {
"self": "https://open-api.artworker.io/workflow/100/task/fixup",
"files": [
"https://open-api.artworker.io/workflow/100/task/import/files/1"
]
}
}
],
"links": {
"self": "https://open-api.artworker.io/workflow/100"
}
}
This endpoint is asynchronous and immediately responds the workflow status, even if the workflow has not completed yet.
Returns
Field | Type | Description |
---|---|---|
id | int | Unique identifier of the workflow. |
uuid | string | User-defined unique ID to track the workflow. |
status | string | Current status of the workflow: one of pending , running ,
completed , or error . |
tasks | array | List of tasks in the workflow. See the "Get Tasks" endpoint for task model details. |
createdAt | string | ISO 8601 timestamp when the workflow was created. |
endedAt | string | ISO 8601 timestamp when the workflow finished. |
links | object | Links for this workflow. Always contains self |
Get a Task
Get https://open-api.artworker.io /v1/taskapi/workflows/100/task/fixup?api_key=[API_KEY]
Sample Response
{
"id": 201,
"operation": "run/pdf-advanced-edit",
"name": "fixup",
"dependsOn": "import",
"payload": {
"options": {
"removePrinterMarks": {
"enabled": true
}
},
"pageRange": "1"
},
"status": "completed",
"error": null,
"createdAt": "2024-12-18T11:00:03.725411Z",
"startedAt": "2024-12-18T11:00:03.725411Z",
"endedAt": "2024-12-18T11:00:03.811505Z",
"links": {
"self": "https://open-api.artworker.io/workflow/100/task/fixup",
"files": [
"https://open-api.artworker.io/workflow/100/task/import/files/1"
]
}
}
Returns
Field | Type | Description |
---|---|---|
id | int | Unique identifier of the task. |
operation | string | Name of the operation, for example import/URL or run/pdf-advanced-edit . |
dependsOn | string | Name of previous task in workflow. |
payload | object | Your submitted payload for the tasks. Depends on the operation type. |
status | string | Current status of the task: one of pending , running , completed ,
or error . |
createdAt | string | ISO 8601 timestamp when the task was created. |
startedAt | string | ISO 8601 timestamp when the task started. |
endedAt | string | ISO 8601 timestamp when the task finished. |
links | object | Links for this task. Always contains self but frequently contains a list of
files depending on the operation. Each link to a file returns the result of the task for the
specified file |
Tasks
Import from URL Task
POST https://open-api.artworker.io /v1/taskapi/workflows?api_key=[API_KEY]
Sample Body
{
"uuid": "myworkflow-123",
"tasks": {
"import": {
"operation": "import/URL",
"payload": {
"urls": ["https://storage.googleapis.com/kudo-web-assets/upload-examples/example_five.pdf"]
}
},
...
}
}
This task accepts a list of urls of files to import into the Artworker system. Each job must start with an import task.
Operation
import/URL
Options
Field | Type | Description |
---|---|---|
urls | string array | List of urls of files to import ready for processing. |
Results
There are no results available for this operation
Advanced PDF Edit Task
POST https://open-api.artworker.io /v1/taskapi/workflows?api_key=[API_KEY]
Sample Body
{
"uuid": "myworkflow-123",
"tasks": {
"fixup": {
"operation": "run/pdf-advanced-edit",
"input": "import",
"payload": {
"pageRange": "1",
"outputFilenames": [{
"fileNum": 1,
"outputFilename": "output.pdf"
}],
"options":{
"removePrinterMarks": {
"enabled": true
},
"removeContentOutsideBleed": {
"enabled": true
},
"addCropMarks": {
"enabled": false
},
"pageRotation": {
"enabled": false,
"angle": 0,
"pageSelector": ""
},
"removePage": {
"enabled": false,
"pageSelector": ""
},
"addPage": {
"enabled": false,
"beforeAfter": "After",
"pageSelector": "1",
"numberOfCopies": 1,
"copyContent": false
},
"splitPage": {
"enabled": false,
"pageSelector": "1*",
"reorderPage": false
},
"bleedboxFixGeometry": {
"enabled": true
},
"optimisePDF": {
"enabled": true
},
"renameLayer": {
"enabled": false,
"layerRegEx": ".*",
"newName": ""
},
"removeLayer": {
"enabled": false,
"layerRegEx": ".*"
},
"removeContentFromLayer": {
"enabled": true
},
"flattenLayers": {
"enabled": false
},
"splitInHalf": {
"enabled": false
},
"readerSpreads": {
"enabled": false,
"coverPage": true
},
"resizePage": {
"enabled": false,
"width": 210,
"height": 297,
"method": "homothetical"
},
"generateBleed": {
"enabled": true,
"sizeLeft": 3.0,
"sizeRight": 3.0,
"sizeTop": 3.0,
"sizeBottom": 3.0,
"minCheck": 80.0,
"method": "mirror",
"generateOnLayer": true,
"bleedLayerName": "generatedBleed"
},
"embedOutputIntent": {
"enabled": true,
"outputIntent": "ISO Coated v2 300% (ECI)"
},
"convertRegistrationToBlack": {
"enabled": false
},
"knockoutWhite": {
"enabled": true,
"applyTo": "Vector-Text"
},
"overprintBlackText": {
"enabled": true,
"minTextSize": 9.0
},
"convertTextToOutlines": {
"enabled": false
}
}
}
}
}
}
This task accepts a list of urls of files to import into the Artworker system. Each job must start with an import task.
Operation
run/pdf-advanced-edit
Payload
Field | Type | Description |
---|---|---|
pageRange | string schema | Range of pages to apply changes to. See page selector |
outputFilenames | array [{ "fileNum": 1, "outputFilename": "output.pdf"}] | Array of filenames with specific file numbers |
options | object | list of pdf preflight options, see below for details |
Document
REMOVE PRINTER MARKS
Printer marks (crop marks and other registration elements) will be detected (as mush as it is possible in an automated process) and removed. This cannot be turned off.
REMOVE CONTENT OUTSIDE BLEED
Any content present outside the bleed box will be removed. This cannot be turned off.
ADD CROP MARKS
Crop marks, aligned on the trim box, can be added. Please note that this action will happen near the end of the process, once the trimbox and the bleedbox have been correctly setup.
Field | Type | Description | Required | Default |
---|---|---|---|---|
addCropMarks.enabled | Boolean | Activate or deactivate the fixup | false | false |
ROTATE PAGE(S)
PDF pages can be rotated by a specific angle, defined by the variable rotateAngle. The default value is 0. The selection of pages can be passed as the variable pageSelector (see page-selector schema).
Field | Type | Description | Required | Default |
---|---|---|---|---|
pageRotation.enabled | Boolean | Activate or deactivate the fixup | false | false |
pageRotation.angle | Number | Angle for rotation (0, 90, 180, or 270) | false | 0 |
pageRotation.pageSelector | String schema | List of pages to be rotated | false | "" |
REMOVE PAGE(S)
PDF pages can be removed. The selection of pages can be passed as the variable pageSelector (see page-selector schema).
Field | Type | Description | Required | Default |
---|---|---|---|---|
removePage.enabled | Boolean | Activate or deactivate the fixup | false | false |
removePage.pageSelector | String schema | List of pages to be removed | false | "" |
ADD PAGE(S)
PDF pages can be added. Pages are added before or after each current selected page. This is defined with the variable bedforeAfter. The default value is After. The selection of pages is passed to the fixup using the variable pageSelector (see page-selector schema). This fixup can add a copy of the current page (which allows duplication) or a blank page, according the variable copyContent. The default value is false, which means that a blank page will be added. With the variable numberOfCopies, it is possible to duplicate the page(s) more than one time. The default value is 1, which means one copy.
Field | Type | Description | Required | Default |
---|---|---|---|---|
addPage.enabled | Boolean | Activate or deactivate the fixup | false | false |
addPage.beforeAfter | String | Add the page before or after the current page (“Before”/“After”) | false | After |
addPage.pageSelector | String schema | List of pages where pages will be added | false | 1 |
addPage.numberOfCopies | Number | Number of times the page should be duplicated | false | 1 |
addPage.copyContent | Boolean | Whether the added page is blank or a copy of the current page | false | false |
SPLIT AND REORDER PAGES
The PDF file can be split into separate PDF files. The split scheme is passed using the variable pageSelector (see page-selector schema). The default value is 1*, which means every page. Merging the pages again at the end of the process results of a reordering of the pages. This is triggered by the variable reorderPage.
Field | Type | Description | Required | Default |
---|---|---|---|---|
splitPage.enabled | Boolean | Activate or deactivate the fixup | false | false |
splitPage.pageSelector | String schema | Split scheme | false | 1* |
splitPage.reorderPage | Boolean | Activate or deactivate the reordering instead of split | false | false |
SET BLEED AND GEOMETRY BOXES
Geometry boxes, and in particular bleedbox can be setup. This one is very important for the bleed generation to be performed. It should always be on.
Field | Type | Description | Required | Default |
---|---|---|---|---|
bleedboxFixGeometry.enabled | Boolean | Activate or deactivate the fixup | false | true |
OPTIMISE PDF
The PDF is optimised for fast web view, so it can be served more quickly over the Internet by a web server that supports byte serving.
Field | Type | Description | Required | Default |
---|---|---|---|---|
optimisePDF.enabled | Boolean | Activate or deactivate the fixup | false | true |
Layers
RENAME LAYER
Layers (optional content group) can be renamed in the PDF file. The list of the layers to be renamed is controlled by the variable layerRegEx, which is a regular expression (to give the most flexible options). The layer(s) will be renamed to the variable newName.
Field | Type | Description | Required | Default |
---|---|---|---|---|
renameLayer.enabled | Boolean | Activate or deactivate the fixup | false | false |
renameLayer.layerRegEx | String | Regular expression to match layers to be renamed | false | .* |
renameLayer.newName | String | Defines the new name of the layer(s) | false | "" |
REMOVE LAYER
Layers (optional content group) can be removed from the PDF file. The list of the layers to be removed is controlled by the variable layerRegEx, which is a regular expression (to give the most flexible options). The layer can be removed with and without the actual content on the layer, controlled by the variable toggleRemoveContentFromLayer. The default value is 1, which means that the content will also be removed from the file.
Field | Type | Description | Required | Default |
---|---|---|---|---|
removeLayer.enabled | Boolean | Activate or deactivate the fixup | false | false |
removeLayer.layerRegEx | String | Regular expression to match layers to be removed | false | .* |
Field | Type | Description | Required | Default |
---|---|---|---|---|
removeContentFromLayer.enabled | Boolean | Whether the content has to be removed as well | false | true |
FLATTEN LAYERS
Layers (optional content group) can be flattened. Please note that that this action will also remove any content on hidden layer(s).
Field | Type | Description | Required | Default |
---|---|---|---|---|
flattenLayers.enabled | Boolean | Activate or deactivate the fixup | false | false |
Pages
SPLIT IN HALF
The PDF pages can be split in half. This action recognises if the page is a single or a double page automatically.
Field | Type | Description | Required | Default |
---|---|---|---|---|
splitInHalf.enabled | Boolean | Activate or deactivate the fixup | false | false |
READER SPREADS
This action arranges the pages in two-page spread without reordering the pages. A cover page (single page) can be used during the process (to keep book spreads), this is controlled by the variable coverPage. The default value is true, which means that the cover page will be used.
Field | Type | Description | Required | Default |
---|---|---|---|---|
readerSpreads.enabled | Boolean | Activate or deactivate the fixup | false | false |
readerSpreads.coverPage | Boolean | Uses a cover page (single page) during the process | false | true |
Dimensions
RESIZE PAGE
There are two resize options, you can resize homothetically or by stretching the artwork to fit the targeted
dimensions. this is controlled by the variable resizeMethod. Possible values are homothetical
and
stretch to fit
.
When the resize is homothetic, the artwork is resized to fit the complete artwork into the new dimension.
White space may be visible left and right or top and bottom, if the new size is not nomothetical to the
original size. The process plan can handle all combinations, portrait on portrait, landscape on landscape,
portrait on landscape and landscape on portrait.
The requested size of the artwork’s trimbox is defined by the variables targetPageWidth and
targetPageHeight. The default values are 210mm wide by 297mm tall.
Field | Type | Description | Required | Default |
---|---|---|---|---|
resizePage.enabled | Boolean | Activate or deactivate the fixup | false | false |
resizePage.width | Number | Target width of the trimbox of the artwork | false | 210 |
resizePage.height | Number | Target height of the trimbox of the artwork | false | 297 |
resizePage.method | String | Method for resize: "homothetical" or "stretch to fit" | false | homothetical |
GENERATE BLEED
The requested size of the bleed is defined by side, with the corresponding variables bleedSizeLeft, bleedSizeRight, bleedSizeTop and bleedSizeBottom. The default value is 3mm for all sides. If existing, the bleedbox will be resized to the value of the trimbox + bleedSize(side), cropbox and mediabox will be adjusted accordingly.
CHECK BLEED
First of all, the PDF file is checked to find out if bleed is necessary (white background on the edges does not require any bleed), then it will be checked to see if enough bleed is present (bleed size should be equal or bigger than bleedSize(side)). If this is the case, the existing bleed will be kept. The minimum required bleed (size that is acceptable, even if less than the requested size) is controlled by the variable bleedMinCheck. The default value is 80 (80%). Note 1: for example for a 3mm requested bleed, the acceptable bleed size would be 2.4mm if the value is 80%. Note 2: to force check to the required bleed size (no tolerance), use the value 100 (100%). If there is no bleed or there is not enough bleed, the engine will generate the missing bleed. If there is enough bleed, no bleed will be generated. If the existing bleed is bigger than the requested bleed, the over-bleed content will be removed and the bleedbox will be set to the requested size.
GENERATE BLEED
The necessary bleed will be generated at bleedSize(side) bleed size (for each side). The method for bleed generation can be “mirror”, “pixel repetition” or “stretch”. The algorithm is controlled by the variable bleedMethod. The default value is mirror. To improve the visual result of the bleed, the generated bleed will start where existing content stops. It can be at trimbox (if there is no bleed at all), or away from trimbox (if there was some bleed, but not enough). To ease selection of generated bleed (e.g. for removal if not good enough), the bleed can be generated on a specific layer (controlled by the variable onLayer), named after the variable bleedLayerName. The default value is generatedBleed.
Field | Type | Description | Required | Default |
---|---|---|---|---|
generateBleed.enabled | Boolean | Activate or deactivate the fixup | false | true |
generateBleed.sizeLeft | Number | Size of the bleed on the left side of the page | false | 3.0 |
generateBleed.sizeRight | Number | Size of the bleed on the right side of the page | false | 3.0 |
generateBleed.sizeTop | Number | Size of the bleed on the top side of the page | false | 3.0 |
generateBleed.sizeBottom | Number | Size of the bleed on the bottom side of the page | false | 3.0 |
generateBleed.minCheck | Number | Acceptable bleed size from required bleed size (%) | false | 80.0 |
generateBleed.method | String | Method for bleed generation: "mirror", "pixel repetition", or "stretch" | false | mirror |
generateBleed.generateOnLayer | Boolean | Activate bleed generation on a specific layer | false | true |
generateBleed.bleedLayerName | String | Name of the bleed layer if generated on a specific layer | false | generatedBleed |
Colours
EMBED OUTPUT INTENT
Output intent can be embedded in the file. The output intent is selected from a fixed list (the list can be updated but this requires a modification of the process plan) and defined by the variable outputIntent. The default value is ISO Coated v2 300% (ECI).
Field | Type | Description | Required | Default |
---|---|---|---|---|
embedOutputIntent.enabled | Boolean | Activate or deactivate the fixup | false | true |
embedOutputIntent.outputIntent | String | Defines the output intent to be embedded. The value can be 'ISO Coated v2 300% (ECI)', 'ISO Coated v2 (ECI)', 'PSO Uncoated ISO12647 (ECI)', 'PSO Coated v3 (ECI)', or 'PSO Uncoated v3 (ECI)' | false | ISO Coated v2 300% (ECI) |
CONVERT REGISTRATION TO BLACK INSIDE TRIMBOX
If registration colour has been used inside the trimbox by mistake, it can be converted to black, on overprint.Black text can be setup on overprint to avoid mis-registration when placed on a coloured background. This is particularly useful for small texts. The minimum text size under which the overprint must be setup is controlled by the variable overprintBlackTextMinimumSize. The default value is 9.
Field | Type | Description | Required | Default |
---|---|---|---|---|
convertRegistrationToBlack.enabled | String | Activate or deactivate the fixup | false | ISO Coated v2 300% (ECI) |
Overprinting
KNOCKOUT WHITE TEXT AND/OR VECTOR OBJECTS
White objects (vector objects and/or text) can be improperly setup to overprint, which means that the object will not be visible anymore. This fixup corrects the overprint flag by putting it on knockout. The fixup can be applied to text, vector objects, or both, according to the variable applyKnockoutWhite. The default value is Vector-Text.
Field | Type | Description | Required | Default |
---|---|---|---|---|
knockoutWhite.enabled | Boolean | Activate or deactivate the fixup | false | true |
knockoutWhite.applyTo | String | Defines on which objects the fixup will perform. The value can be “Text”, “Vector” or “Vector-Text” | false | Vector-Text |
OVERPRINT BLACK TEXT
Black text can be setup on overprint to avoid mis-registration when placed on a coloured background. This is particularly useful for small texts. The minimum text size under which the overprint must be setup is controlled by the variable overprintBlackTextMinimumSize. The default value is 9.
Field | Type | Description | Required | Default |
---|---|---|---|---|
overprintBlackText.enabled | Boolean | Activate or deactivate the fixup | false | true |
overprintBlackText.minTextSize | Number | The text size under which the overprint will be set up | false | 9.0 |
Fonts
CONVERT TEXT TO OUTLINES
This fixup will outline fonts. Please note that some fonts may still remain as live text, if the font’s license does not allow to outline.
Field | Type | Description | Required | Default |
---|---|---|---|---|
convertTextToOutlines.enabled | Boolean | Activate or deactivate the fixup | false | false |
Results
GET https://open-api.artworker.io /v1/taskapi/workflows/100/task/fixup/files/1?api_key=[API_KEY]
Sample Response
{
"output_file_url": "https://storage.cloud.google.com/preflight-profile-output-bucket/123/d39b0efe-9982-4161-bbd0-1074a8169d8f.pdf",
"output_filename": "some-output.pdf",
"report": {
"bleedboxFixGeometry": {
"details": {
"message": "",
"numFail": 0,
"numPass": 6
},
"retCode": 5
}
}
}
The results will be available at
/v1/taskapi/workflows/:workflowId/task/:taskName/files/:fileNumber
Task Error Codes
This section covers error codes found in the task.error
object that are specific to this task.
Error Code | Description |
---|---|
503, 508 | At least one error executing fixups. |
100 - 104 | An error occurred starting fixups. |
105, 106, 107 | The provided file is encrypted or damaged and in need of repair. |
130 - 159 | Fixups were terminated prematurely. Please contact support |
Response
Field | Type | Description |
---|---|---|
output_file_url | String | URL of created file |
output_filename | String | If provided, custom output filename |
report | object | If provided, custom output filename |
Details
Field | Type | Description |
---|---|---|
message | String | error or warning message if available |
numFail | Number | Number of fails |
numPass | Number | Number of passes |
RetCode
Code Number | Description |
---|---|
0 | No hit, no Fixups executed |
1 | At least one hit with severity ‘info’, no Fixups executed |
2 | At least one hit with severity ‘warning’, no Fixups executed |
3 | At least one hit with severity ‘error’, no Fixups executed |
5 | No hit, Fixups have been executed |
6 | At least one hit with severity ‘info’, Fixups have been executed |
7 | At least one hit with severity ‘warning’, Fixups have been executed |
8 | At least one hit with severity "error", Fixups have been executed; Fixups failed |
Page Selector
A split scheme expression can be a number with an asterisk *
or a more complex string.
Number with Asterisk *
- Groups pages into chunks of the defined size.
- Example:
"3*"
will group the PDF into groups of 3 pages.
Simple Expressions
Type | Syntax | Example | Description |
---|---|---|---|
Simple expression | number[-number] |
1-5 |
Pages 1 to 5: [1,2,3,4,5] |
5-1 |
Pages 5 to 1 in reverse: [5,4,3,2,1] |
||
8 |
Only page 8 | ||
-1 |
Last page | ||
-3--1 |
Last 3 pages: [n, n-1, n-2] |
||
-1--3 |
Last 3 pages in reverse: [n-2, n-1, n] |
||
-1-3 |
Last n - 2 pages in reverse: [n, ..., 3] |
Simple Expression with Simple Range
Type | Syntax | Example | Description |
---|---|---|---|
Simple expression with Simple Range | number[-number]_number[-number]["," joker$] |
1-2_-2--1 |
First 2 and last 2 pages: [1,2,n-1,n] |
1-2_-2--1,$ |
First 2, last 2, and remaining inner pages: [1,2,n-1,n,3,...,n-2] |
||
1_1_1_1 |
4 times page 1: [1,1,1,1] |
Multipage Expressions
Type | Syntax | Example | Description |
---|---|---|---|
Even pages | even_pages |
even |
All even pages (same as *2(2) ) |
Odd pages | uneven_pages |
odd |
All odd pages (same as *2(1) ) |
Packages of pages | number*[(start_page)] |
5* |
Packages of 5 pages |
5*(2) |
Packages of 5 pages, starting with page 2 | ||
Every nth page | *number[(start_page)] |
*5 |
Every 5th page |
*5(2) |
Every 5th page, starting with page 2 | ||
*5(-20) |
Every 5th page of the last 20 pages (total 4 pages) | ||
*number[(start_page,end_page)] |
*5(2,20) |
Every 5th page, starting from page 2 to page 20 |
Simple Expression List
Type | Syntax | Example | Description |
---|---|---|---|
Simple expression list | simple_expression {"," simple_expression}[ "," joker$] |
1-5,8,-3--1 |
Pages 1-5, page 8, and the last 3 pages of the PDF |
1-5,8,-1--3 |
Pages 1-5, page 8, and the last 3 pages in reverse order | ||
1-5,8,$ |
Pages 1-5, page 8, and all remaining pages |
Joker Expression
Type | Syntax | Example | Description |
---|---|---|---|
Joker | <expression>,$ |
1-5,8,-3--1,$ |
Pages 1-5, page 8, the last 3 pages, and the rest of the pages of the PDF, grouped separately. |
Summary
These expressions allow flexible page selection and grouping for PDF manipulation. The syntax supports:
1. Simple expressions (specific pages or ranges).
2. Complex combinations (e.g., ranges with joker $
).
3. Patterns for regular intervals (e.g., every 5th page).