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 |