Save Tokens and Shop Endpoints

Manage save tokens — the ids that identify your buyers’ saved designs — plus cart thumbnails and AI access keys. All endpoints are POST requests with a JSON body to https://api.printess.com. See the Backend API Reference for authentication and how Try It Live works.

Extend Save Token Lifetime

POSThttps://api.printess.com/savetoken/lifetime/extenduser

Keep a purchased design (and its uploaded images) available beyond the default 30 days.

A save token — the id the buyer-side editor hands to your shop when the customer finished a design — lives for 30 days by default. When the customer actually buys, call this endpoint to keep the design and all buyer-uploaded resources (images, etc.) available for reprints, complaints and archiving.

expiresOn is the absolute new expiration date, not a duration. There is no upper limit; additional costs apply for extended lifetimes.

Important: an already expired (or deleted) save token cannot be resurrected — extend the lifetime BEFORE the 30 days are over, ideally right at order confirmation. Also note that setting a date in the past immediately invalidates the token.

Call this at order-confirmation time, before triggering production. The save token comes from the buyer-side editor’s onAddToBasket / save callback.

Request Body

PropertyDescription
saveTokenrequired
string
The save token from the buyer-side editor. Always starts with st:, total length 89 characters.
expiresOnrequired
string (date-time)
The new absolute expiration date (UTC), e.g. 2031-01-01T00:00:00Z. Choose a date far in the future to keep the design practically forever.

Try It Live

Requests are sent to https://api.printess.com/savetoken/lifetime/extend with your Service Token.

Code Example

Ready-to-use code with the minimal payload. Replace YOUR_PRINTESS_SERVICE_TOKEN with your Service Token.

// Keep a purchased design (and its uploaded images) available beyond the default 30 days.
const response = await fetch("https://api.printess.com/savetoken/lifetime/extend", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PRINTESS_SERVICE_TOKEN"
  },
  body: JSON.stringify({
    "saveToken": "st:YOUR_SAVE_TOKEN",
    "expiresOn": "2031-01-01T00:00:00Z"
  })
});

if (!response.ok) {
  throw new Error("Printess API error " + response.status + ": " + await response.text());
}

const result = await response.json();
console.log(result);
curl -X POST "https://api.printess.com/savetoken/lifetime/extend" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN" \
  -d '{
  "saveToken": "st:YOUR_SAVE_TOKEN",
  "expiresOn": "2031-01-01T00:00:00Z"
}'
// Keep a purchased design (and its uploaded images) available beyond the default 30 days.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

var payload = @"{
  ""saveToken"": ""st:YOUR_SAVE_TOKEN"",
  ""expiresOn"": ""2031-01-01T00:00:00Z""
}";

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_PRINTESS_SERVICE_TOKEN");

    var content = new StringContent(payload, Encoding.UTF8, "application/json");
    var response = await client.PostAsync("https://api.printess.com/savetoken/lifetime/extend", content);

    if (!response.IsSuccessStatusCode)
    {
        throw new HttpRequestException("Printess API error " + (int)response.StatusCode + ": " + await response.Content.ReadAsStringAsync());
    }

    var result = await response.Content.ReadAsStringAsync();
    Console.WriteLine(result);
}
<?php
// Keep a purchased design (and its uploaded images) available beyond the default 30 days.
$payload = [
    'saveToken' => 'st:YOUR_SAVE_TOKEN',
    'expiresOn' => '2031-01-01T00:00:00Z',
];

$ch = curl_init('https://api.printess.com/savetoken/lifetime/extend');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status < 200 || $status >= 300) {
    throw new RuntimeException("Printess API error $status: $response");
}

$result = json_decode($response, true);
print_r($result);

Response

Returns 200 with an empty body on success.

Errors

Status / Code Meaning
400 saveToken or expiresOn missing.
406 (c: 202) Save token not found — or it is already expired and can no longer be extended.

List Save Tokens

POSThttps://api.printess.com/savetoken/listowner

Browse and search all live save tokens of your account.

Returns the not-yet-expired save tokens of your account, 50 per page, newest first. Use it in back-office tooling: find the designs of a specific shop customer, look up the token behind a basket id, or audit what is stored.

The response is a plain array without a total count — request the next page until fewer than 50 items are returned.

Request Body

PropertyDescription
saveToken
string
Exact match on one save token.
templateName
string
Substring match on the template name (case-sensitive).
shopBasketId
string
Exact match on the basket id your shop attached when the design was saved.
shopUserId
string
Exact match on the shop user id attached when the design was saved. Special: you can also pass a save token (st:...) here to find all designs saved by the same buyer as that token.
startDate
string (date-time)
Only tokens created on or after this date.
endDate
string (date-time)
Only tokens created on or before this date. Send an explicit end-of-day timestamp (e.g. ...T23:59:59Z) to include the whole day.
page
integerdefault: 1
1-based page number. The page size is fixed at 50.

Try It Live

Requests are sent to https://api.printess.com/savetoken/list with your Service Token.

Code Example

Ready-to-use code with the minimal payload. Replace YOUR_PRINTESS_SERVICE_TOKEN with your Service Token.

// Browse and search all live save tokens of your account.
const response = await fetch("https://api.printess.com/savetoken/list", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PRINTESS_SERVICE_TOKEN"
  },
  body: JSON.stringify({})
});

if (!response.ok) {
  throw new Error("Printess API error " + response.status + ": " + await response.text());
}

const result = await response.json();
console.log(result);
curl -X POST "https://api.printess.com/savetoken/list" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN" \
  -d '{}'
// Browse and search all live save tokens of your account.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

var payload = @"{}";

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_PRINTESS_SERVICE_TOKEN");

    var content = new StringContent(payload, Encoding.UTF8, "application/json");
    var response = await client.PostAsync("https://api.printess.com/savetoken/list", content);

    if (!response.IsSuccessStatusCode)
    {
        throw new HttpRequestException("Printess API error " + (int)response.StatusCode + ": " + await response.Content.ReadAsStringAsync());
    }

    var result = await response.Content.ReadAsStringAsync();
    Console.WriteLine(result);
}
<?php
// Browse and search all live save tokens of your account.
$payload = (object) [];

$ch = curl_init('https://api.printess.com/savetoken/list');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status < 200 || $status >= 300) {
    throw new RuntimeException("Printess API error $status: $response");
}

$result = json_decode($response, true);
print_r($result);

Response

A plain array of save token entries, newest first.

PropertyDescription
saveToken
string
The save token.
createdOn
string (date-time)
When the design was saved.
expiresOn
string (date-time)
Current expiration date. null = never expires.
templateName
string
The template the design is based on.
shopBasketId
string
The basket id your shop attached when saving.

Errors

Status / Code Meaning
403 The token is not owner-level (this is a back-office endpoint).

Save Token Info

POSThttps://api.printess.com/shop/template/infouser

Check whether a save token still exists and when it expires.

A cheap metadata probe for a save token: creation date, expiration date and the shop identifiers (basket id, shop user id) that were attached when the design was saved. Call it before checkout to decide whether you need to extend the lifetime.

Note: an expiresOn of 1999-01-01T00:00:00Z means the token was deleted.

Request Body

PropertyDescription
idrequired
string
The save token (st:...).

Try It Live

Requests are sent to https://api.printess.com/shop/template/info with your Service Token.

Code Example

Ready-to-use code with the minimal payload. Replace YOUR_PRINTESS_SERVICE_TOKEN with your Service Token.

// Check whether a save token still exists and when it expires.
const response = await fetch("https://api.printess.com/shop/template/info", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PRINTESS_SERVICE_TOKEN"
  },
  body: JSON.stringify({
    "id": "st:YOUR_SAVE_TOKEN"
  })
});

if (!response.ok) {
  throw new Error("Printess API error " + response.status + ": " + await response.text());
}

const result = await response.json();
console.log(result);
curl -X POST "https://api.printess.com/shop/template/info" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN" \
  -d '{
  "id": "st:YOUR_SAVE_TOKEN"
}'
// Check whether a save token still exists and when it expires.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

var payload = @"{
  ""id"": ""st:YOUR_SAVE_TOKEN""
}";

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_PRINTESS_SERVICE_TOKEN");

    var content = new StringContent(payload, Encoding.UTF8, "application/json");
    var response = await client.PostAsync("https://api.printess.com/shop/template/info", content);

    if (!response.IsSuccessStatusCode)
    {
        throw new HttpRequestException("Printess API error " + (int)response.StatusCode + ": " + await response.Content.ReadAsStringAsync());
    }

    var result = await response.Content.ReadAsStringAsync();
    Console.WriteLine(result);
}
<?php
// Check whether a save token still exists and when it expires.
$payload = [
    'id' => 'st:YOUR_SAVE_TOKEN',
];

$ch = curl_init('https://api.printess.com/shop/template/info');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status < 200 || $status >= 300) {
    throw new RuntimeException("Printess API error $status: $response");
}

$result = json_decode($response, true);
print_r($result);

Response

PropertyDescription
createdOn
string (date-time)
When the design was saved.
expiresOn
string (date-time)
Current expiration date. null = never expires; 1999-01-01T00:00:00Z = deleted.
basketId
string
The shop basket id attached at save time.
shopUserId
string
The shop user id attached at save time.
shopUserDisplay
string
The shop user display name attached at save time.

Errors

Status / Code Meaning
406 (c: 101) id missing.
404 Save token not found (empty response body).

Basket Thumbnail URL

POSThttps://api.printess.com/shop/basket/thumbnailuser

Get an image URL showing the buyer’s design — for the cart and order emails.

Turns a save token into a signed, publicly fetchable PNG URL that shows the buyer’s personalized design. Perfect for the shopping cart line item, the order confirmation email and back-office order views.

No image is rendered during this call — the returned URL renders (and caches) the thumbnail on first access, so the call itself is fast.

Request Body

PropertyDescription
saveTokenrequired
string
The save token of the design (st:...).
width
integerdefault: 400
Thumbnail width in pixels, maximum 1000.
height
integerdefault: 400
Thumbnail height in pixels, maximum 1000.

Try It Live

Requests are sent to https://api.printess.com/shop/basket/thumbnail with your Service Token.

Code Example

Ready-to-use code with the minimal payload. Replace YOUR_PRINTESS_SERVICE_TOKEN with your Service Token.

// Get an image URL showing the buyer's design — for the cart and order emails.
const response = await fetch("https://api.printess.com/shop/basket/thumbnail", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PRINTESS_SERVICE_TOKEN"
  },
  body: JSON.stringify({
    "saveToken": "st:YOUR_SAVE_TOKEN"
  })
});

if (!response.ok) {
  throw new Error("Printess API error " + response.status + ": " + await response.text());
}

const result = await response.json();
console.log(result);
curl -X POST "https://api.printess.com/shop/basket/thumbnail" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN" \
  -d '{
  "saveToken": "st:YOUR_SAVE_TOKEN"
}'
// Get an image URL showing the buyer's design — for the cart and order emails.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

var payload = @"{
  ""saveToken"": ""st:YOUR_SAVE_TOKEN""
}";

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_PRINTESS_SERVICE_TOKEN");

    var content = new StringContent(payload, Encoding.UTF8, "application/json");
    var response = await client.PostAsync("https://api.printess.com/shop/basket/thumbnail", content);

    if (!response.IsSuccessStatusCode)
    {
        throw new HttpRequestException("Printess API error " + (int)response.StatusCode + ": " + await response.Content.ReadAsStringAsync());
    }

    var result = await response.Content.ReadAsStringAsync();
    Console.WriteLine(result);
}
<?php
// Get an image URL showing the buyer's design — for the cart and order emails.
$payload = [
    'saveToken' => 'st:YOUR_SAVE_TOKEN',
];

$ch = curl_init('https://api.printess.com/shop/basket/thumbnail');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status < 200 || $status >= 300) {
    throw new RuntimeException("Printess API error $status: $response");
}

$result = json_decode($response, true);
print_r($result);

Response

Returns the thumbnail URL as a plain JSON string. The image renders on first access and is cached afterwards.

Errors

Status / Code Meaning
400 saveToken missing, or width / height not positive.

Delete Save Token

POSThttps://api.printess.com/saveToken/deleteservice

Permanently delete a saved design — e.g. for GDPR requests or cart cleanup.

Deletes the stored design JSON of a save token and marks the token expired, which also releases the buyer-uploaded resources for cleanup. Call it when a buyer cancels, an abandoned cart is purged, or a data-deletion request comes in.

This cannot be undone — a deleted save token can neither be loaded nor have its lifetime extended.

Request Body

PropertyDescription
saveTokenrequired
string
The save token to delete (st:..., 89 characters). Must belong to your account.

Try It Live

Requests are sent to https://api.printess.com/saveToken/delete with your Service Token.

Code Example

Ready-to-use code with the minimal payload. Replace YOUR_PRINTESS_SERVICE_TOKEN with your Service Token.

// Permanently delete a saved design — e.g. for GDPR requests or cart cleanup.
const response = await fetch("https://api.printess.com/saveToken/delete", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PRINTESS_SERVICE_TOKEN"
  },
  body: JSON.stringify({
    "saveToken": "st:YOUR_SAVE_TOKEN"
  })
});

if (!response.ok) {
  throw new Error("Printess API error " + response.status + ": " + await response.text());
}

const result = await response.json();
console.log(result);
curl -X POST "https://api.printess.com/saveToken/delete" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN" \
  -d '{
  "saveToken": "st:YOUR_SAVE_TOKEN"
}'
// Permanently delete a saved design — e.g. for GDPR requests or cart cleanup.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

var payload = @"{
  ""saveToken"": ""st:YOUR_SAVE_TOKEN""
}";

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_PRINTESS_SERVICE_TOKEN");

    var content = new StringContent(payload, Encoding.UTF8, "application/json");
    var response = await client.PostAsync("https://api.printess.com/saveToken/delete", content);

    if (!response.IsSuccessStatusCode)
    {
        throw new HttpRequestException("Printess API error " + (int)response.StatusCode + ": " + await response.Content.ReadAsStringAsync());
    }

    var result = await response.Content.ReadAsStringAsync();
    Console.WriteLine(result);
}
<?php
// Permanently delete a saved design — e.g. for GDPR requests or cart cleanup.
$payload = [
    'saveToken' => 'st:YOUR_SAVE_TOKEN',
];

$ch = curl_init('https://api.printess.com/saveToken/delete');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status < 200 || $status >= 300) {
    throw new RuntimeException("Printess API error $status: $response");
}

$result = json_decode($response, true);
print_r($result);

Response

Returns 200 with an empty body on success.

Errors

Status / Code Meaning
406 (c: 100) The value is not a valid save token.
404 Save token not found in your account.

Create AI Auth Key

POSThttps://api.printess.com/ai/auth/createservice

Mint a per-buyer AI usage key with its own budget.

Creates a short-lived AI access key that limits how much of your AI credit budget a single buyer session can use. Your backend requests a key when a buyer opens the designer and passes it to the editor, which sends it with every AI request (image generation, image editing, text AI). Without such a key, AI access is controlled account-wide.

accessRights maps a scope to a budget. Scopes can be a specific AI feature (e.g. Flux Schnell, SDXL, gpt-image-1, Face Swap), a feature group (textToImage, imageEdit, llm, misc), or all as a catch-all. Budgets: {"type": "fixed", "amount": 5} allows 5 uses total; {"type": "rateLimit", "amount": 10, "period": "hour"} allows 10 uses per period (5minutes, hour or day); {"type": "unrestricted"} allows unlimited use; {"type": "base"} blocks the scope entirely.

Request Body

PropertyDescription
expirationDaterequired
string (date-time)
When the key expires, in UTC (e.g. 2026-08-17T12:00:00Z). Maximum 7 days in the future. Always send this — omitting it produces a key that expires immediately.
accessRightsrequired
map<string, AccessRight>
Scope-to-budget map. Keys: an AI feature name, a feature group (textToImage, imageEdit, llm, misc) or all. Values: {"type": "fixed", "amount": n}, {"type": "rateLimit", "amount": n, "period": "5minutes"|"hour"|"day"}, {"type": "unrestricted"} or {"type": "base"} (block).

Try It Live

Requests are sent to https://api.printess.com/ai/auth/create with your Service Token.

Code Example

Ready-to-use code with the minimal payload. Replace YOUR_PRINTESS_SERVICE_TOKEN with your Service Token.

// Mint a per-buyer AI usage key with its own budget.
const response = await fetch("https://api.printess.com/ai/auth/create", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PRINTESS_SERVICE_TOKEN"
  },
  body: JSON.stringify({
    "expirationDate": "2026-12-31T23:59:59Z",
    "accessRights": {
      "all": {
        "type": "fixed",
        "amount": 5
      }
    }
  })
});

if (!response.ok) {
  throw new Error("Printess API error " + response.status + ": " + await response.text());
}

const result = await response.json();
console.log(result);
curl -X POST "https://api.printess.com/ai/auth/create" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN" \
  -d '{
  "expirationDate": "2026-12-31T23:59:59Z",
  "accessRights": {
    "all": {
      "type": "fixed",
      "amount": 5
    }
  }
}'
// Mint a per-buyer AI usage key with its own budget.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

var payload = @"{
  ""expirationDate"": ""2026-12-31T23:59:59Z"",
  ""accessRights"": {
    ""all"": {
      ""type"": ""fixed"",
      ""amount"": 5
    }
  }
}";

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_PRINTESS_SERVICE_TOKEN");

    var content = new StringContent(payload, Encoding.UTF8, "application/json");
    var response = await client.PostAsync("https://api.printess.com/ai/auth/create", content);

    if (!response.IsSuccessStatusCode)
    {
        throw new HttpRequestException("Printess API error " + (int)response.StatusCode + ": " + await response.Content.ReadAsStringAsync());
    }

    var result = await response.Content.ReadAsStringAsync();
    Console.WriteLine(result);
}
<?php
// Mint a per-buyer AI usage key with its own budget.
$payload = [
    'expirationDate' => '2026-12-31T23:59:59Z',
    'accessRights' => [
        'all' => [
            'type' => 'fixed',
            'amount' => 5,
        ],
    ],
];

$ch = curl_init('https://api.printess.com/ai/auth/create');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer YOUR_PRINTESS_SERVICE_TOKEN',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status < 200 || $status >= 300) {
    throw new RuntimeException("Printess API error $status: $response");
}

$result = json_decode($response, true);
print_r($result);

Response

Returns the generated key as a plain JSON string. Hand it to the buyer-side editor for the current session.

Errors

Status / Code Meaning
400 / 406 (c: 100) accessRights missing or body empty.
406 (c: 102) expirationDate is more than 7 days in the future.
403 The token is not a Service Token (this endpoint requires service-level auth).