Use Case: Updating Virtual Products with Additional Artwork
When we create virtual products using the createVirtualProductsFromArtwork
GraphQL mutation, we are applying artwork to the first print area (usually the front), but what if we wanted to also populate other print areas such as the back or neck label? This article will describe how you can make a single subsequent API call to achieve this and update other aspects of the product as well.
We will first use the createVirtualProductsFromArtwork
GraphQL mutation, providing it with a single blank product and a single artwork object. The API will return details of a new virtual product created in the platform.
This could easily be 10 blank products and 10 artwork objects, returning 100 new virtual products but for the purposes of this example and to keep things easy to understand, we will just create 1 virtual product.
We will then use the response data to update the following parts of the new virtual product:
Add artwork to the Back print area.
Add artwork to the Neck Label print area.
Change the name of the product.
Change the retail SKU of the product.
Disable specific colour options on the product.
Set the default colour option.
Authentication
The GraphQL API uses oauth authentication. A request for an oauth token is made to the oauth endpoint, which returns an access token. This token can then be used in requests made to the GraphQL API endpoint.
To make a request for a token, you will require an oauth user to be set up in the KornitX platform. The user will require specific access and permissions depending on the API request. The permissions required for this request can be found in the “Oauth User Requirements” section below.
If you don’t have an oauth user set up, please contact the support team, who will be happy to help. The support team will set up the oauth user in the KornitX platform for you and supply you with the oauth user client ID and client secret. These credentials can then be used to obtain a token from the oauth token endpoint.
Oauth Token Endpoint - https://oauth.kornitx.net/token
The oauth token can be obtained by making a POST to the above endpoint. The request type for the oauth token is x-www-form-urlencoded
and must include the following form keys and values.
Key | Value |
---|---|
| The client ID of the oauth user provided by the support team. |
| The client secret of the oauth user provided by the support team. |
|
|
|
|
Example Response
{"token_type":"Bearer","expires_in":3600,"access_token":"..."}
Oauth User Requirements
To make the createVirtualProductsFromArtwork
request to the GraphQL API, the oauth user must have:
Read access to the categories that the products listed in the
baseProducts
variable, are assigned to.Write access to the target category specified in the
categoryId
variable.The
products.customisable.create
user permission enabled.
The Create Virtual Products from Artwork GraphQL Mutation
Now we have the access token, we can now make the createVirtualProductsFromArtwork
request.
We will be making a POST request to the https://cpp.custom-gateway.net/v2/product-manager/products-graphql
endpoint.
The request will have 2 headers listed below.
Content-Type: “application/json”
Authorization: “Bearer [OAUTH_ACCESS_TOKEN]“
[OAUTH_ACCESS_TOKEN] should be replaced by the access token that was returned when we made the token request to the https://oauth.kornitx.net/token
endpoint.
Mutation
In this example, we will be including 1 base product ID and 1 artwork object, which will create a single virtual product and return the following information about that product.
Product ID
Name
Retail SKU
Various snapshots
The aspect options of the blank product that the new virtual product was created using (giving us the information we need to disable various colours later on).
The print areas (known as surface areas) of the blank product that the new virtual product was created using (giving us the information we need to add artwork to the back and neck label print areas later on).
However, the GraphQL API call can return numerous other pieces of information about the product, details of which, can be found in the schema here - https://developers-v2.custom-gateway.net/graphql/product.doc.html
Example Mutation
mutation (
$baseProducts: [ID]!
$categoryId: ID!
$artwork: [CreateVirtualProductsFromArtworkArtwork]!
) {
createVirtualProductsFromArtwork(
baseProducts: $baseProducts
categoryId: $categoryId
artwork: $artwork
) {
id
name
retail_sku
base_product {
aspect_options(count: 1000) {
items {
aspect_id
aspect_name
id
name
is_enabled
}
}
surface_areas {
items {
id
name
}
}
}
snapshots {
thumbnail
extra_small
small
medium
large
extra_large
super_large
}
base_product_id
}
}
Variables
The mutation contains references to 3 variables - $baseProducts
, $categoryId
and $artwork
. Descriptions of these variables can be found in the table below.
Variable Descriptions
Variable | Type | Description |
---|---|---|
|
| A collection of base product IDs. |
|
| The ID of the target product category into which the new virtual products will be created. |
|
| A collection of artwork objects. Each artwork object has a:
|
Example Variables
{
"baseProducts":[
8843396
],
"categoryId":20097,
"artwork":[
{
"design_name":"Army Print",
"urls":[
{
"preview":"https://s3-eu-west-1.amazonaws.com/user-images-gateway3d-com/user-images/0f34/6511/9dcb/d926/624b/7b12/e625/413b/e254/1bcb/b445/7369/16d6/1ca4/3441/4195-original.jpg",
"original":"https://s3-eu-west-1.amazonaws.com/user-images-gateway3d-com/user-images/0f34/6511/9dcb/d926/624b/7b12/e625/413b/e254/1bcb/b445/7369/16d6/1ca4/3441/4195-original.jpg"
}
]
}
]
}
Response
A successful request will return the details of the virtual products that were created. For the example we have been working with, the response data can be viewed below.
Example Response
{
"data": {
"createVirtualProductsFromArtwork": [
{
"id": 14700144,
"name": "Army Print - Gildan Valueweight T-Shirt",
"retail_sku": "Gd01test-14700144",
"base_product": {
"aspect_options": {
"items": [
{
"aspect_id": 1785850,
"aspect_name": "Front",
"id": 2514439,
"name": "Black",
"is_enabled": true
},
{
"aspect_id": 1785850,
"aspect_name": "Front",
"id": 2514440,
"name": "Red",
"is_enabled": true
},
{
"aspect_id": 1785850,
"aspect_name": "Front",
"id": 2514441,
"name": "Navy",
"is_enabled": true
},
{
"aspect_id": 1785850,
"aspect_name": "Front",
"id": 2514442,
"name": "Sport Grey",
"is_enabled": true
},
{
"aspect_id": 1785850,
"aspect_name": "Front",
"id": 2514443,
"name": "Daisy",
"is_enabled": true
},
{
"aspect_id": 1785850,
"aspect_name": "Front",
"id": 2514444,
"name": "Maroon",
"is_enabled": true
},
{
"aspect_id": 1785850,
"aspect_name": "Front",
"id": 2514445,
"name": "Forest Green",
"is_enabled": true
},
{
"aspect_id": 1785850,
"aspect_name": "Front",
"id": 2514446,
"name": "Royal Blue",
"is_enabled": true
},
{
"aspect_id": 1785850,
"aspect_name": "Front",
"id": 2514447,
"name": "Light Blue",
"is_enabled": true
},
{
"aspect_id": 1785850,
"aspect_name": "Front",
"id": 2514448,
"name": "Irish Green",
"is_enabled": true
},
{
"aspect_id": 1785850,
"aspect_name": "Front",
"id": 2514449,
"name": "White",
"is_enabled": true
},
{
"aspect_id": 1785851,
"aspect_name": "Back",
"id": 2514450,
"name": "Black",
"is_enabled": true
},
{
"aspect_id": 1785851,
"aspect_name": "Back",
"id": 2514451,
"name": "Red",
"is_enabled": true
},
{
"aspect_id": 1785851,
"aspect_name": "Back",
"id": 2514452,
"name": "Navy",
"is_enabled": true
},
{
"aspect_id": 1785851,
"aspect_name": "Back",
"id": 2514453,
"name": "Sport Grey",
"is_enabled": true
},
{
"aspect_id": 1785851,
"aspect_name": "Back",
"id": 2514454,
"name": "Irish Green",
"is_enabled": true
},
{
"aspect_id": 1785851,
"aspect_name": "Back",
"id": 2514455,
"name": "Daisy",
"is_enabled": true
},
{
"aspect_id": 1785851,
"aspect_name": "Back",
"id": 2514456,
"name": "Maroon",
"is_enabled": true
},
{
"aspect_id": 1785851,
"aspect_name": "Back",
"id": 2514457,
"name": "Forest Green",
"is_enabled": true
},
{
"aspect_id": 1785851,
"aspect_name": "Back",
"id": 2514458,
"name": "Royal Blue",
"is_enabled": true
},
{
"aspect_id": 1785851,
"aspect_name": "Back",
"id": 2514459,
"name": "Light Blue",
"is_enabled": true
},
{
"aspect_id": 1785851,
"aspect_name": "Back",
"id": 2514460,
"name": "White",
"is_enabled": true
},
{
"aspect_id": 1785852,
"aspect_name": "Neck Label",
"id": 2514461,
"name": "White",
"is_enabled": true
},
{
"aspect_id": 1785852,
"aspect_name": "Neck Label",
"id": 2514462,
"name": "Black",
"is_enabled": true
},
{
"aspect_id": 1785852,
"aspect_name": "Neck Label",
"id": 2514463,
"name": "Red",
"is_enabled": true
},
{
"aspect_id": 1785852,
"aspect_name": "Neck Label",
"id": 2514464,
"name": "Sport Grey",
"is_enabled": true
},
{
"aspect_id": 1785852,
"aspect_name": "Neck Label",
"id": 2514465,
"name": "Navy",
"is_enabled": true
},
{
"aspect_id": 1785852,
"aspect_name": "Neck Label",
"id": 2514466,
"name": "Irish Green",
"is_enabled": true
},
{
"aspect_id": 1785852,
"aspect_name": "Neck Label",
"id": 2514467,
"name": "Daisy",
"is_enabled": true
},
{
"aspect_id": 1785852,
"aspect_name": "Neck Label",
"id": 2514468,
"name": "Forest Green",
"is_enabled": true
},
{
"aspect_id": 1785852,
"aspect_name": "Neck Label",
"id": 2514469,
"name": "Royal Blue",
"is_enabled": true
},
{
"aspect_id": 1785852,
"aspect_name": "Neck Label",
"id": 2514470,
"name": "Light Blue",
"is_enabled": true
},
{
"aspect_id": 1785852,
"aspect_name": "Neck Label",
"id": 2514471,
"name": "Maroon",
"is_enabled": true
}
]
},
"surface_areas": {
"items": [
{
"id": 4606942,
"name": "Front",
"artworks": {
"items": []
}
},
{
"id": 4606943,
"name": "Back",
"artworks": {
"items": []
}
},
{
"id": 4606944,
"name": "Neck Label",
"artworks": {
"items": []
}
},
{
"id": 4637180,
"name": "Front (Paid)",
"artworks": {
"items": []
}
},
{
"id": 4637181,
"name": "Back (Paid)",
"artworks": {
"items": []
}
}
]
}
},
"snapshots": {
"extra_small": "https://s3-eu-west-1.amazonaws.com/generated-assets-gateway3d-com/product/7F17D091A45AAFF/snapshot/extra-small.jpg",
"small": "https://s3-eu-west-1.amazonaws.com/generated-assets-gateway3d-com/product/7F17D091A45AAFF/snapshot/small.jpg",
"medium": "https://s3-eu-west-1.amazonaws.com/generated-assets-gateway3d-com/product/7F17D091A45AAFF/snapshot/medium.jpg",
"large": "https://s3-eu-west-1.amazonaws.com/generated-assets-gateway3d-com/product/7F17D091A45AAFF/snapshot/large.jpg",
"extra_large": "https://s3-eu-west-1.amazonaws.com/generated-assets-gateway3d-com/product/7F17D091A45AAFF/snapshot/extra-large.jpg",
"super_large": "https://s3-eu-west-1.amazonaws.com/generated-assets-gateway3d-com/product/7F17D091A45AAFF/snapshot/super-large.jpg"
},
"base_product_id": 8843396
}
]
}
}
Updating the New Virtual Product
Now that we have created the virtual product, we can go ahead and update it using the data returned in the previous call. We will make a single call to the GraphQL API but the payload will contain 5 separate mutations.
We can use the same access token as we did for the createVirtualProductsFromArtwork
GraphQL mutation, as we included the products.customisable.edit
permission in the scope when we requested the OAuth token. We should however, use the https://graphql.kornitx.net
endpoint when making this request.
A mutation to add artwork to the Back print area.
backArtwork: updateProductSurfaceAreaArtwork(
productId: $productId,
surfaceAreaId: $surfaceAreaBackId,
artworks: $backArtworks
)
{
id
surface_id
fullsize_url
preview_url
type
is_required_for_virtuals
}
A mutation to add artwork to the Neck Label print area.
neckArtwork: updateProductSurfaceAreaArtwork(
productId: $productId,
surfaceAreaId: $surfaceAreaNeckId,
artworks: $neckArtworks
)
{
id
surface_id
fullsize_url
preview_url
type
is_required_for_virtuals
}
As we are making 2 updateProductSurfaceAreaArtwork
mutations, the API requires us to provide aliases so that there aren’t any conflicts in terms of the data returned in the response. We are using the aliases backArtwork
and neckArtwork
.
A mutation to update the product name and retail SKU.
updateProducts(products: $products) {
id
name
retail_sku
}
A mutation to disable 2 specific colour options on the virtual product.
updateProductVirtualAspectOptions(productId: $productId, options: $aspectOptions) {
id
option_id
is_enabled
}
A mutation to set the default colour option.
updateProductVirtualAspects(productId: $productId, aspects: $aspects) {
id
aspect_id
default_option_id
}
When combined together, the full GraphQL request will look like this.
mutation(
$productId: ID!,
$surfaceAreaBackId: ID!,
$surfaceAreaNeckId: ID!,
$backArtworks: [ProductSurfaceAreaArtworkInput]!,
$neckArtworks: [ProductSurfaceAreaArtworkInput]!,
$products: [ProductInput]!,
$aspectOptions: [ProductVirtualAspectOptionInput]!
$aspects: [ProductVirtualAspectInput]!
)
{
core {
backArtwork: updateProductSurfaceAreaArtwork(
productId: $productId,
surfaceAreaId: $surfaceAreaBackId,
artworks: $backArtworks
)
{
id
surface_id
fullsize_url
preview_url
type
is_required_for_virtuals
}
neckArtwork: updateProductSurfaceAreaArtwork(
productId: $productId,
surfaceAreaId: $surfaceAreaNeckId,
artworks: $neckArtworks
)
{
id
surface_id
fullsize_url
preview_url
type
is_required_for_virtuals
}
updateProducts(products: $products) {
id
name
retail_sku
}
updateProductVirtualAspectOptions(productId: $productId, options: $aspectOptions) {
id
option_id
is_enabled
}
updateProductVirtualAspects(productId: $productId, aspects: $aspects) {
id
aspect_id
default_option_id
}
}
}
Variables
The values of the following variables will either be taken from the response data from the previous createVirtualProductsFromArtwork
mutation or values that you should supply like the artwork URLs for the Back and Neck Label print areas.
Variable Descriptions
Variable | Type | Description |
---|---|---|
|
| The ID of the virtual product to be updated. This can be found in the response data of the previous mutation. |
|
| The ID of the back print area. This can be found in the response data of the previous mutation. |
|
| The ID of the neck label print area. This can be found in the response data of the previous mutation. |
|
| A collection of product surface area artwork input objects. Each artwork object has a:
|
|
| A collection of product surface area artwork input objects. Each artwork object has a:
|
|
| A collection of product input objects. The product input object has the fields:
|
|
| A collection of product virtual aspect option input objects. Each artwork object has the fields:
When disabling aspect options, it’s important that we disable each colour option on all aspects. In our example we are disabling Light Blue and Irish Green and there are 3 aspects, Front, Back and Neck Label. We should therefore send a total of 6 aspect option input objects. These will consist of:
The IDs of each of these can be found in the response data of the previous mutation. |
|
| A collection of product virtual aspect input objects.
It’s important that we include an object for each aspect. In this case, there will be 3 objects, one each for the Front, Back and Neck Label aspects. It’s also important that each aspect option we set as default, is related to the same colour. In our example, we will be setting Red as the default colour, so each of the aspect option IDs we send in the request, will be related to the Red aspect option. |
Example Variables
{
"productId": 14700144,
"surfaceAreaBackId": 4606943,
"surfaceAreaNeckId": 4606944,
"backArtworks": [
{
"fullsize_url": "https://s3-eu-west-1.amazonaws.com/user-images-gateway3d-com/user-images/52d8/2cf7/b89d/8fc2/b969/bdb3/aea9/b9bb/0d32/a14c/0c2d/9f88/0d3b/c435/300b/305b-original.jpg",
"preview_url": "https://s3-eu-west-1.amazonaws.com/user-images-gateway3d-com/user-images/52d8/2cf7/b89d/8fc2/b969/bdb3/aea9/b9bb/0d32/a14c/0c2d/9f88/0d3b/c435/300b/305b-original.jpg",
"type": "raster",
"is_required_for_virtuals": true
}
],
"neckArtworks": [
{
"fullsize_url": "https://s3-eu-west-1.amazonaws.com/user-images-gateway3d-com/user-images/9b46/78c2/01f6/43f9/0866/21f7/08f0/2304/9ad8/d16e/4ed6/81f1/1a01/1029/72e1/84bc-original.png",
"preview_url": "https://s3-eu-west-1.amazonaws.com/user-images-gateway3d-com/user-images/9b46/78c2/01f6/43f9/0866/21f7/08f0/2304/9ad8/d16e/4ed6/81f1/1a01/1029/72e1/84bc-original.png",
"type": "raster",
"is_required_for_virtuals": true
}
],
"products": [
{
"id": 14700144,
"name": "New Product Name",
"retail_sku": "PS_SKU_12345"
}
],
"aspectOptions": [
{
"id": null,
"option_id": 2514447,
"is_enabled": false
},
{
"id": null,
"option_id": 2514448,
"is_enabled": false
},
{
"id": null,
"option_id": 2514459,
"is_enabled": false
},
{
"id": null,
"option_id": 2514454,
"is_enabled": false
},
{
"id": null,
"option_id": 2514466,
"is_enabled": false
},
{
"id": null,
"option_id": 2514470,
"is_enabled": false
}
],
"aspects": [
{
"id": null,
"aspect_id": 1785850,
"default_option_id": 2514440
},
{
"id": null,
"aspect_id": 1785851,
"default_option_id": 2514451
},
{
"id": null,
"aspect_id": 1785852,
"default_option_id": 2514463
}
]
}
Response
A successful request will return the details of the virtual products that were updated. For the example we have been working with, the response data can be viewed below.
Example Response
{
"data": {
"core": {
"backArtwork": [
{
"id": 5140064,
"surface_id": 4606943,
"fullsize_url": "https://s3-eu-west-1.amazonaws.com/user-images-gateway3d-com/user-images/52d8/2cf7/b89d/8fc2/b969/bdb3/aea9/b9bb/0d32/a14c/0c2d/9f88/0d3b/c435/300b/305b-original.jpg",
"preview_url": "https://s3-eu-west-1.amazonaws.com/user-images-gateway3d-com/user-images/52d8/2cf7/b89d/8fc2/b969/bdb3/aea9/b9bb/0d32/a14c/0c2d/9f88/0d3b/c435/300b/305b-original.jpg",
"type": "raster",
"is_required_for_virtuals": true
}
],
"neckArtwork": [
{
"id": 5140065,
"surface_id": 4606944,
"fullsize_url": "https://s3-eu-west-1.amazonaws.com/user-images-gateway3d-com/user-images/9b46/78c2/01f6/43f9/0866/21f7/08f0/2304/9ad8/d16e/4ed6/81f1/1a01/1029/72e1/84bc-original.png",
"preview_url": "https://s3-eu-west-1.amazonaws.com/user-images-gateway3d-com/user-images/9b46/78c2/01f6/43f9/0866/21f7/08f0/2304/9ad8/d16e/4ed6/81f1/1a01/1029/72e1/84bc-original.png",
"type": "raster",
"is_required_for_virtuals": true
}
],
"updateProducts": [
{
"id": 14702553,
"name": "New Product Name",
"retail_sku": "PS_SKU_12345"
}
],
"updateProductVirtualAspectOptions": [
{
"id": 1485949,
"option_id": 2514447,
"is_enabled": false
},
{
"id": 1485950,
"option_id": 2514448,
"is_enabled": false
},
{
"id": 1485951,
"option_id": 2514459,
"is_enabled": false
},
{
"id": 1485952,
"option_id": 2514454,
"is_enabled": false
},
{
"id": 1485953,
"option_id": 2514466,
"is_enabled": false
},
{
"id": 1485954,
"option_id": 2514470,
"is_enabled": false
}
],
"updateProductVirtualAspects": [
{
"id": 175470,
"aspect_id": 1785850,
"default_option_id": "2514440"
},
{
"id": 175471,
"aspect_id": 1785851,
"default_option_id": "2514451"
},
{
"id": 175472,
"aspect_id": 1785852,
"default_option_id": "2514463"
}
]
}
}
}