Commit a design
const url = 'https://api.pixonaut.app/v1/designs?lang=en';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"externalRef":"cart-10482-1","fulfilmentPayload":{"variantSku":"TEE-BLACK-M"},"proofToken":"eyJhdWQiOiJwcm9vZiIsImlkIjoicHJmXzljMWUyZDNmNGE1YjZjN2Q4ZTlmMGExYiIsInQiOiJhY21lIiwiZXhwIjoxNzkyNDkxMjQ3MDAwfQ.EXAMPLE_signature_not_a_real_one_0000000000"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url 'https://api.pixonaut.app/v1/designs?lang=en' \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "externalRef": "cart-10482-1", "fulfilmentPayload": { "variantSku": "TEE-BLACK-M" }, "proofToken": "eyJhdWQiOiJwcm9vZiIsImlkIjoicHJmXzljMWUyZDNmNGE1YjZjN2Q4ZTlmMGExYiIsInQiOiJhY21lIiwiZXhwIjoxNzkyNDkxMjQ3MDAwfQ.EXAMPLE_signature_not_a_real_one_0000000000" }'Operation ID: designs.commit
Commits a customer’s design, from a proof token (secret or integration key only) or from a template and its values. A printshop it names, or the partner a locked blank is made by, is kept on the design and is where its orders go unless an order names another; with none, an order goes to the blank’s default printshop, else the tenant’s, as they are when the order is made. A fulfilment payload lacking a key is refused 422 missing_fulfilment_keys against where the design would go now, short of the keys that printshop takes only once there is an order (Printful’s recipient); each order checks every required key again against the printshop it goes to, and that check decides. A design holding a spot ink that may not print from its CMYK fallback is refused 422 spot_plate_required the same way, where that printshop takes no spot plates. A design committed from a template is fitted to and records the blank and placement it names, and a named placement that does not resolve is refused 422 unknown_placement; one committed from a proof token records the proof’s. Only a secret or integration key may attach a fulfilment payload, an external reference or choose the printshop.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”The IANA timezone the template’s dynamic values are resolved in, such as Europe/Stockholm: today’s date there. Absent, the workspace’s timezone.
The IANA timezone the template’s dynamic values are resolved in, such as Europe/Stockholm: today’s date there. Absent, the workspace’s timezone.
The language the template’s dynamic values are written in when their name names none, one of en, sv, de, fr, es, nl, da, nb, fi. Absent, the workspace’s default language. A value whose name carries a language, {date.long:sv}, keeps it.
The language the template’s dynamic values are written in when their name names none, one of en, sv, de, fr, es, nl, da, nb, fi. Absent, the workspace’s default language. A value whose name carries a language, {date.long:sv}, keeps it.
Header Parameters
Section titled “Header Parameters”Your own key for this request. A repeat with the same key and body within 24 hours is answered with what the first one made, marked Idempotent-Replayed: true, and makes nothing; the same key with another body is refused idempotency_key_reused, and a repeat while the first is still being answered idempotency_key_in_use. A request that is refused makes nothing, so its key may be sent again.
Your own key for this request. A repeat with the same key and body within 24 hours is answered with what the first one made, marked Idempotent-Replayed: true, and makes nothing; the same key with another body is refused idempotency_key_reused, and a repeat while the first is still being answered idempotency_key_in_use. A request that is refused makes nothing, so its key may be sent again.
Request Bodyrequired
Section titled “Request Bodyrequired”object
The order data a printshop needs to fulfil this design, such as a material or a shipping method: a JSON object of your own keys, which Pixonaut keeps and hands on with the order without reading its keys. Its size and nesting depth are limited. Only a secret or integration key may send it, null included; a publishable key sending it is refused with secret_key_required.
The id of the printshop that makes this design’s orders, for a design on no blank. A design on a blank is made by the blank’s printshop, set when the blank was created: naming any other is refused with printshop_differs_from_blank, and the design keeps the blank’s printshop even once the blank is deleted. Absent or null, a design on no blank goes to the tenant’s default printshop as it is when the order is made. Only a secret or integration key may send it, null included; a publishable key sending it is refused with secret_key_required.
Your own reference for this design, such as your cart or order line id: kept exactly as sent, not unique, and never read by Pixonaut. GET /v1/designs?externalRef= finds the designs holding it, and PUT /v1/designs/{id}/external-ref replaces it. Only a secret or integration key may send it; a publishable key sending it is refused with secret_key_required.
Approve the design as it is committed, so it is never awaiting approval: an explicit approval by the caller, recorded as design.approved. Needs designs:update: a secret key and an integration key hold it, a member may, and a publishable key never does; a caller without it is refused with forbidden. Left out or false, the design waits for approval.
object
What the customer entered: an object keyed by the id of the template layer each value is for, holding that layer’s properties (a text layer’s content, for instance). Checked against the template when the design is committed.
The linked group the placement is designed as part of: every placement one design drives, this one among them, each with whether its print is mirrored. The print is mirrored when this placement’s entry says so, and a repeat on it is laid at one physical scale across the group: the document records the group and the width of its widest placement’s print area (linked.referenceWidthMm). Needs blankId and placementId; each placement must be one of the blank’s.
object
Placements one design drives, two at least.
object
Whether the placement’s print is mirrored left to right.
The id of one of the blank’s placements.
The order data a printshop needs to fulfil this design, such as a material or a shipping method: a JSON object of your own keys, which Pixonaut keeps and hands on with the order without reading its keys. Its size and nesting depth are limited. Only a secret or integration key may send it, null included; a publishable key sending it is refused with secret_key_required.
The id of the printshop that makes this design’s orders, for a design on no blank. A design on a blank is made by the blank’s printshop, set when the blank was created: naming any other is refused with printshop_differs_from_blank, and the design keeps the blank’s printshop even once the blank is deleted. Absent or null, a design on no blank goes to the tenant’s default printshop as it is when the order is made. Only a secret or integration key may send it, null included; a publishable key sending it is refused with secret_key_required.
Your own reference for this design, such as your cart or order line id: kept exactly as sent, not unique, and never read by Pixonaut. GET /v1/designs?externalRef= finds the designs holding it, and PUT /v1/designs/{id}/external-ref replaces it. Only a secret or integration key may send it; a publishable key sending it is refused with secret_key_required.
Approve the design as it is committed, so it is never awaiting approval: an explicit approval by the caller, recorded as design.approved. Needs designs:update: a secret key and an integration key hold it, a member may, and a publishable key never does; a caller without it is refused with forbidden. Left out or false, the design waits for approval.
Whether the designer drew the customer’s canvas at the template’s own ratio, as the SDK mount option of that name sets it. The design is made at the chosen size through the template’s fit either way, so this changes nothing in what is made.
A variant of the blank, by ref (v_…). On a blank whose print areas change with its size, the design is sized at, and keeps, that variant’s size; a ref the blank has no variant of is refused with variant_not_of_blank. On any other blank it is not checked. A proof also keeps it as proofVariant, for display.
The size the design is for, as the blank’s option values, such as {"Size": "XL"}, in place of variant: a value of each option the blank’s print areas change with, and nothing else, or it is refused with variant_row_invalid. Ignored on a blank whose print areas change with nothing.
object
The variant whose colour the design is drawn in, by ref (v_…), when it is not the one variant names: on a dark colour each layer takes its on-dark value. It sizes nothing. A proof keeps it as proofVariant, so its commit is drawn in the same colour. Absent, variant’s colour; a ref the blank has no variant of draws as on a light product.
Lays the design as a repeat of its template across the print area. Null, or absent, places it once. Through a designer link, a repeat the link offers, or null where its shopper may turn the repeat off; absent there, the link’s own start.
object
How the tiles are laid: grid lines them up, brick moves every other row along by half a tile, halfDrop moves every other column down by half a tile, and scatter strews them at random places, turns and sizes, arranged by seed.
Which arrangement a scatter draws: another seed is another arrangement of the same tile. Read by scatter only.
The tile’s width in percent of the print area’s width, above 0 and at most 100; the tile keeps the template’s shape. A tile that would print under 10 mm on a side is drawn at 10 mm.
Examples
A connected store, from connect to delivery: 3. Commit the design with the store's reference
{ "externalRef": "cart-10482-1", "fulfilmentPayload": { "variantSku": "TEE-BLACK-M" }, "proofToken": "eyJhdWQiOiJwcm9vZiIsImlkIjoicHJmXzljMWUyZDNmNGE1YjZjN2Q4ZTlmMGExYiIsInQiOiJhY21lIiwiZXhwIjoxNzkyNDkxMjQ3MDAwfQ.EXAMPLE_signature_not_a_real_one_0000000000"}Cart lifetimes and proof expiry: Commit at checkout
{ "fulfilmentPayload": { "variantSku": "TEE-BLACK-M" }, "proofToken": "eyJhdWQiOiJwcm9vZiIsImlkIjoicHJmXzljMWUyZDNmNGE1YjZjN2Q4ZTlmMGExYiIsInQiOiJhY21lIiwiZXhwIjoxNzkyNDkxMjQ3MDAwfQ.EXAMPLE_signature_not_a_real_one_0000000000"}Design to order: 1. The customer commits a design
{ "blankId": "blank_tshirt", "placementId": "front", "templateId": "tshirt-basic@2", "values": { "name": { "content": "Alexandra" } }}Example
{ "fulfilmentPayload": { "material": "cotton", "shippingMethod": "standard" }, "printshopId": "0b1c2d3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e", "proofToken": "eyJhdWQiOiJwcm9vZiIsImlkIjoicHJmXzljMWUyZDNmNGE1YjZjN2Q4ZTlmMGExYiIsInQiOiJhY21lIiwiZXhwIjoxNzkyNDkxMjQ3MDAwfQ.EXAMPLE_signature_not_a_real_one_0000000000"}Front and back on one item: 1. Commit a design for each placement
{ "blankId": "blank_tshirt", "placementId": "back", "templateId": "tshirt-back@1", "values": { "name": { "content": "Alexandra" } }}Responses
Section titled “Responses”The committed design
object
The pictures that print below printFloorDpi at the design’s print size. A warning: nothing is refused for it.
object
The picture’s pixels along the edge that decides.
Pixels per inch along that edge, as printed.
The layer the picture fills, or the artwork’s own key for its image background.
The pixels that edge needs at the floor.
The minimum print resolution the design’s pictures were judged against: the template’s own, else the tenant’s.
Examples
A connected store, from connect to delivery: 3. Commit the design with the store's reference
{ "designId": "6f1c8a2b-3d4e-4f5a-8b6c-7d8e9f0a1b2c", "lowResolution": [], "printFloorDpi": 150}Design to order: 1. The customer commits a design
{ "designId": "6f1c8a2b-3d4e-4f5a-8b6c-7d8e9f0a1b2c", "lowResolution": [], "printFloorDpi": 150}Example
{ "designId": "6f1c8a2b-3d4e-4f5a-8b6c-7d8e9f0a1b2c", "lowResolution": [], "printFloorDpi": 150}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: placement_not_committable, print_size_not_committable, repeat_not_committable, bad_request, invalid_query
object
Always sent with invalid_query.
Examples
bad_request
{ "error": "bad_request"}invalid_query
{ "error": "invalid_query", "reason": "string"}placement_not_committable
{ "error": "placement_not_committable"}print_size_not_committable
{ "error": "print_size_not_committable"}repeat_not_committable
{ "error": "repeat_not_committable"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: unauthorized
object
Examples
unauthorized
{ "error": "unauthorized"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: secret_key_required, forbidden, origin_forbidden, feature_disabled, workspace_suspended
object
The feature the tenant does not have. Always sent with feature_disabled.
Examples
feature_disabled
{ "error": "feature_disabled", "feature": "api"}forbidden
{ "error": "forbidden"}origin_forbidden
{ "error": "origin_forbidden"}secret_key_required
{ "error": "secret_key_required"}workspace_suspended
{ "error": "workspace_suspended"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: unknown_proof, not_found
object
Examples
not_found
{ "error": "not_found"}unknown_proof
{ "error": "unknown_proof"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: proof_already_committed, correction_proof, layout_proof, idempotency_key_in_use
object
Always sent with proof_already_committed.
Examples
correction_proof
{ "error": "correction_proof"}idempotency_key_in_use
{ "error": "idempotency_key_in_use"}layout_proof
{ "error": "layout_proof"}Placing an order safely: A proof token commits once
{ "designId": "6f1c8a2b-3d4e-4f5a-8b6c-7d8e9f0a1b2c", "error": "proof_already_committed"}proof_already_committed
{ "designId": "string", "error": "proof_already_committed"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: proof_expired
object
Examples
proof_expired
{ "error": "proof_expired"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: idempotency_key_reused, invalid_idempotency_key, invalid_doc, invalid_fulfilment_payload, payload_too_large, missing_fulfilment_keys, spot_plate_required, unknown_printshop, printshop_disconnected, printshop_unavailable, printshop_differs_from_blank, constraint_violation, unknown_placement, variant_not_of_blank, variant_row_invalid, variant_required, asset_map_too_large
object
Always sent with variant_required.
Always sent with asset_map_too_large, and may be sent with payload_too_large.
Always sent with spot_plate_required.
Always sent with invalid_doc.
Always sent with payload_too_large, asset_map_too_large.
Always sent with missing_fulfilment_keys.
Always sent with unknown_printshop, printshop_disconnected, printshop_unavailable, printshop_differs_from_blank, variant_not_of_blank, variant_row_invalid, variant_required.
Always sent with spot_plate_required.
Always sent with variant_not_of_blank.
Always sent with constraint_violation.
object
On a text_draws_fallback_glyphs or text_draws_missing_glyphs warning: the characters the text’s font cannot draw, each once, in the order the text first holds them. Absent on every other violation.
The language whose overrides break the rule, when only the template as it reads in that language does. Absent, the original.
error refuses a publish; warning is worth the author’s attention and never does.
Examples
asset_map_too_large
{ "bytes": 0, "error": "asset_map_too_large", "maxBytes": 0}constraint_violation
{ "error": "constraint_violation", "violations": [ { "given": {}, "layerId": "string", "prop": "string", "rule": "string", "severity": "error" } ]}Errors
{ "bytes": 70312, "error": "payload_too_large", "maxBytes": 65536}idempotency_key_reused
{ "error": "idempotency_key_reused"}invalid_doc
{ "detail": {}, "error": "invalid_doc"}invalid_fulfilment_payload
{ "error": "invalid_fulfilment_payload"}invalid_idempotency_key
{ "error": "invalid_idempotency_key"}missing_fulfilment_keys
{ "error": "missing_fulfilment_keys", "missing": [ "string" ]}payload_too_large
{ "error": "payload_too_large", "maxBytes": 0}printshop_differs_from_blank
{ "error": "printshop_differs_from_blank", "reason": "string"}printshop_disconnected
{ "error": "printshop_disconnected", "reason": "string"}printshop_unavailable
{ "error": "printshop_unavailable", "reason": "string"}spot_plate_required
{ "cause": "printshop_takes_no_plates", "error": "spot_plate_required", "references": [ "string" ]}unknown_placement
{ "error": "unknown_placement"}unknown_printshop
{ "error": "unknown_printshop", "reason": "string"}variant_not_of_blank
{ "error": "variant_not_of_blank", "reason": "string", "variant": "string"}variant_required
{ "areasVaryBy": [ "string" ], "error": "variant_required", "reason": "string"}variant_row_invalid
{ "error": "variant_row_invalid", "reason": "string"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: rate_limited, link_design_limit
object
When the link makes designs again: when the oldest design counted leaves the window. Null for a total limit. Always sent with link_design_limit.
Examples
link_design_limit
{ "error": "link_design_limit", "reopensAt": 0}rate_limited
{ "error": "rate_limited"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: db_error. A request that failed unexpectedly answers as text instead.
object
Examples
db_error
{ "error": "db_error"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Questions? Write to [email protected].