NAV

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

  1. Identify the events you want to monitor, and the event payloads to parse.
  2. Create a webhook endpoint as an HTTP endpoint on your local server.
  3. Handle requests from Artworker by parsing each event object and returning 200 or 201 response status codes
  4. Test your webhook endpoint is working properly with ngrok
  5. Deploy your webhook endpoint so it's publicly accessible HTTPS URL
  6. 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

  1. A local application serving an endpoint like http://localhost:8080/artworker_webhooks
  2. 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.

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