Create a share link
const url = 'https://api.pixonaut.app/v1/share-links';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"kind":"proof-page","locale":"sv","mayDecide":true,"subjectId":"6f1c8a2b-3d4e-4f5a-8b6c-7d8e9f0a1b2c"}'};
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/share-links \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "kind": "proof-page", "locale": "sv", "mayDecide": true, "subjectId": "6f1c8a2b-3d4e-4f5a-8b6c-7d8e9f0a1b2c" }'Operation ID: shareLinks.create
Opens one hosted page about one template, design or order to whoever holds the link. Answers with the token, which is never shown again. A member may hand out only what they hold themselves; a printshop page takes printshops:update, an address capture page orders:create. A connected store’s integration key hands out what its grants hold, such as a deciding proof page it emails its customer, who approves or rejects there; the page is drawn in the brand named by brandId, or the workspace’s default.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”object
The brand the link’s page is drawn in: its name, logo and accent colour (GET /v1/brands). Refused brand_not_found unless it is one of the workspace’s. Absent, a link a connected store’s key hands out keeps the store’s brand, and any other is drawn in whichever brand is the workspace’s default when it opens. A brand a link that still opens names cannot be deleted.
A designer only: how many designs its page may make, in total or per rolling hour, day or week. Each side approved counts one. At the limit the page, and an approval, answer 429 link_design_limit. Refused design_limit_not_allowed for any other kind. Absent, no limit.
object
How many designs the link may make in its period.
total counts every design the link made; hour, day and week the last 60 minutes, 24 hours or 7 days, rolling.
How long the link works, in days. Absent, the kind’s default; a designer then never expires. Each kind has a cap, named in the refusal when exceeded.
The page the link opens. A correction link is minted for its design by POST /v1/designs/{id}/correction-links.
A proof page only: the language it is shown in, one of en, sv, de, fr, es, nl, da, nb, fi. Absent, the page is shown in the workspace’s default language. The link’s url carries ?lang=<locale> when it names one. Refused locale_not_allowed for any other kind.
A proof page only: whether its holder may approve or reject the design. Handing that out takes designs:update as well as designs:read.
The workspace’s own name for the link (Spring market stand), at most 80 characters, never shown on its page. Trimmed, inner spaces made one; empty is no name. Unique among the workspace’s working links, case aside: one another holds is refused share_link_name_taken naming the holder, a longer one share_link_name_too_long. A withdrawn or expired link frees its name.
An address capture page only: the one order of the design its answer reads and changes, whatever orders of the design are placed later. Refused order_not_found unless it holds a print of the design (and, for a connected store, the store placed it), order_closed once it has shipped, will not be made or its personal data was erased, and order_not_allowed for any other kind. Absent, the page reads and changes the design’s newest open order.
A designer only: whether its page draws the placement frame, the ring and corner handles around the shopper’s picture, at rest, as the SDK’s showPlacementFrame does. Refused placement_frame_not_allowed for any other kind. Absent, the frame shows only while the picture is dragged or sized on the preview.
A designer only: whether its page draws a thin frame around the print area on the product photo, as the SDK’s showPrintAreaFrame does. Refused print_area_frame_not_allowed for any other kind. Absent, no frame.
A proof page only: where it sends the customer once they have asked for changes, with state, so the store can open the design for editing. Refused return_url_not_allowed for any other kind: a designer that returns to a store is minted by POST /v1/templates/{id}/designer-links, a correction page by POST /v1/designs/{id}/correction-links. On one of the origins the tenant’s publishable keys are allowed on.
Carried back to returnUrl untouched, for the store to match the customer to its own session. Only with returnUrl.
What the page is about: a template’s base id for a designer, a design’s id for a proof page or address capture, an order’s id for an order status or printshop page.
Examples
A connected store, from connect to delivery: 5. Or let the customer decide on a proof page
{ "kind": "proof-page", "locale": "sv", "mayDecide": true, "subjectId": "6f1c8a2b-3d4e-4f5a-8b6c-7d8e9f0a1b2c"}Example
{ "expiresInDays": 14, "kind": "proof-page", "mayDecide": true, "subjectId": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f"}Sending the customer back to the store: The proof page
{ "kind": "proof-page", "locale": "sv", "mayDecide": true, "returnUrl": "https://shop.acme.example/account/designs?edit=6f1c8a2b", "state": "edit-7c1e", "subjectId": "6f1c8a2b-3d4e-4f5a-8b6c-7d8e9f0a1b2c"}Responses
Section titled “Responses”The new link
object
The brand the link’s page is drawn in; null for the workspace’s default, whichever that is when it opens.
How many designs a designer link may make; null for none.
object
How many designs the link may make in its period.
total counts every design the link made; hour, day and week the last 60 minutes, 24 hours or 7 days, rolling.
When the link stops working; null for one that never does.
The language the link’s page is shown in, which its url names as ?lang=<locale>; null when it names none, and the page is shown in the workspace’s default language.
The workspace’s name for the link.
Whether a designer link’s page draws the placement frame around the shopper’s picture at rest; false for every other link.
Whether a designer link’s page draws the print area’s frame; false for every other link.
The link’s token. Shown in this response only.
The hosted page the link opens, with ?lang=<locale> when the link names a locale.
Examples
A connected store, from connect to delivery: 5. Or let the customer decide on a proof page
{ "brandId": null, "createdAt": 1790000050000, "designLimit": null, "expiresAt": 1792592050000, "id": "0b1c2d3e-4f50-4a6b-8c7d-000000000010", "kind": "proof-page", "locale": "sv", "mayDecide": true, "name": null, "placementFrame": false, "printAreaFrame": false, "returnUrl": null, "subjectId": "6f1c8a2b-3d4e-4f5a-8b6c-7d8e9f0a1b2c", "token": "EXAMPLE_share_link_token_not_a_real_one_000", "url": "https://app.pixonaut.example/h/proof/EXAMPLE_share_link_token_not_a_real_one_000?lang=sv"}Example
{ "brandId": null, "createdAt": 1760000000000, "designLimit": null, "expiresAt": 1761209600000, "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "kind": "proof-page", "locale": null, "mayDecide": true, "name": null, "placementFrame": false, "printAreaFrame": false, "returnUrl": null, "subjectId": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f", "token": "EXAMPLE_share_link_token_not_a_real_one_000", "url": "https://app.pixonaut.example/h/proof/EXAMPLE_share_link_token_not_a_real_one_000"}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: decide_not_allowed, return_url_not_allowed, return_url_not_https, return_url_off_store, locale_not_allowed, design_limit_not_allowed, print_area_frame_not_allowed, placement_frame_not_allowed, order_not_allowed, expiry_too_long, invalid_input
object
Always sent with expiry_too_long.
Always sent with expiry_too_long.
Always sent with invalid_input.
Examples
decide_not_allowed
{ "error": "decide_not_allowed"}design_limit_not_allowed
{ "error": "design_limit_not_allowed"}expiry_too_long
{ "error": "expiry_too_long", "kind": "designer", "maxDays": 0}invalid_input
{ "error": "invalid_input", "reason": "string"}locale_not_allowed
{ "error": "locale_not_allowed"}order_not_allowed
{ "error": "order_not_allowed"}placement_frame_not_allowed
{ "error": "placement_frame_not_allowed"}print_area_frame_not_allowed
{ "error": "print_area_frame_not_allowed"}return_url_not_allowed
{ "error": "return_url_not_allowed"}return_url_not_https
{ "error": "return_url_not_https"}return_url_off_store
{ "error": "return_url_off_store"}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: plan_limit_reached, origin_forbidden, feature_disabled
object
The feature the tenant does not have. Always sent with feature_disabled.
The limit the tenant is at: templates, connectedStores, apiKeys, shareLinks, customDomains, printsMadePerMonth (prints made without an order this month), members, orders (this month’s orders, which getting a print’s files without an order counts as), or a sandbox’s own caps: sandboxPrintsPerDay, sandboxPrintsPerMonth, sandboxOrdersPerMonth. A sandbox shares every other limit with its live workspace. Always sent with plan_limit_reached.
How many the plan allows. Always sent with plan_limit_reached.
The plan whose limit it is. Always sent with plan_limit_reached.
Examples
feature_disabled
{ "error": "feature_disabled", "feature": "api"}origin_forbidden
{ "error": "origin_forbidden"}plan_limit_reached
{ "error": "plan_limit_reached", "limit": "templates", "max": 0, "plan": "free"}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: subject_not_found, order_not_found, brand_not_found, not_found
object
Examples
brand_not_found
{ "error": "brand_not_found"}not_found
{ "error": "not_found"}order_not_found
{ "error": "order_not_found"}subject_not_found
{ "error": "subject_not_found"}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: share_link_name_taken, order_closed
object
Always sent with order_closed.
The link holding the name. Always sent with share_link_name_taken.
Examples
order_closed
{ "closed": "shipped", "error": "order_closed"}share_link_name_taken
{ "error": "share_link_name_taken", "holderId": "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: share_link_name_too_long, payload_too_large
object
Sent with payload_too_large.
Always sent with payload_too_large.
The longest name a link may have. Always sent with share_link_name_too_long.
Examples
payload_too_large
{ "error": "payload_too_large", "maxBytes": 0}share_link_name_too_long
{ "error": "share_link_name_too_long", "maxLength": 0}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
object
Examples
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.
Refused: lock_timeout
object
Examples
lock_timeout
{ "error": "lock_timeout"}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].