Skip to content

Pixel for your customers

A customer can ask Pixel to change their design in the designer: “write my name in gold”, “make a picture of a fox for the photo”. Pixel changes only what the template offers the customer, within what each field allows, and the change is one step the customer can undo. That includes a photo’s adjustments where the template offers them: “make the photo black and white” sets its tone, and an adjustment the template keeps fixed is not changed, with Pixel saying so.

On a template that lets customers add layers of their own, Pixel can add, change and remove them too: “add a line saying Happy birthday” adds a text layer from the template’s preset and writes it. Pixel adds only the kinds the template allows, and no more of each than its most; a request past either is refused, as the designer refuses the customer, and Pixel’s reply says why. It removes only layers the customer (or Pixel) added, never the template’s own. An answer that adds, removes or changes the customer’s own layers after the customer added or removed one while Pixel worked is not applied, and ask() rejects as for any other failure.

Pixel is off until you turn it on for a template, in its Pixel settings (PUT /v1/templates/by-base/{baseId}/shopper-pixel), where you also choose what Pixel may do (change fields, which includes adding and removing the customer’s own layers, generate a picture, cut a picture out of its background) and how much one designer session may ask. Each request is paid from your workspace’s credits, within those limits and your workspace’s monthly ceiling.

There is nothing to set up. For a template with Pixel on, the designer draws a “Create with AI” button above the form, in Pixonaut.mount() and in your hosted designer links, in your accent. It opens a prompt: Enter sends it, Shift+Enter adds a line, Esc closes it. While Pixel works the customer can cancel, which stops the request and applies nothing of it; once Pixel has changed the design, Undo takes the change back. A request that did not work shows one message under the prompt, with Try again.

The button is drawn only for a template with Pixel on, and only in a designer that holds a publishable key or a designer link. A designer whose requests go through your server (transport) offers none: Pixel answers a customer’s browser, never a server’s secret key.

A designer you build yourself has the same calls under designer.pixel:

Call What it does
available() Whether the template shown offers Pixel. Draw your prompt only when it does.
ask(prompt, { signal }) Ask Pixel to change the design. Resolves { reply, changed, cutOuts, layers } once Pixel’s changes are applied as one step: what Pixel says it did, each { layerId, prop } it changed, each picture it is cutting out, and each layer of the customer’s own it added or removed, as { action: 'added' | 'removed', layerId, kind } by the id it had then. All three empty means Pixel changed nothing: show its reply. signal, optional, cancels it (below).
busy() Whether a request is under way. One runs at a time.
canUndo(), undo() Whether there is a step of Pixel’s to take back on the design shown, and take it back: every field it changed returns to what it held before, except one the customer has changed since, and a cut-out it asked that is still running is stopped. A layer of the customer’s own it added is removed, and one it removed comes back at its place with its values, unless the customer has added or removed one since.

on('pixel') tells your UI how a request stands, whether your code or the built-in control asked it:

status When
'asking' A request was sent.
'done' Its changes are applied; reply, changed, cutOuts and layers as ask() resolves them.
'failed' It did not work.
'cancelled' It was cancelled through its signal.
'undone' undo() took a step back; changed names the fields it restored, and layers the layer changes it took back.

When Pixel cuts a picture out of its background, the cut-out takes the picture’s place once it is done, a moment after ask() resolves, as a customer’s own upload’s cut-out does.

Pass an AbortSignal to cancel a request under way. The request stops, the api stops Pixel’s work on it, nothing it answered is applied, and ask() rejects with the signal’s reason (an AbortError, for abort() with none). on('pixel') hears 'cancelled', never 'failed', and on('error') hears nothing. A cancelled request is paid for as any is: the model calls Pixel made before it stopped.

const controller = new AbortController();
cancel.addEventListener('click', () => controller.abort());
await designer.pixel.ask(prompt.value, { signal: controller.signal });

Whatever stops a request — Pixel turned off, a session’s limit or the monthly ceiling reached, your credits run out, the network down — ask() rejects with a PixelUnavailableError, changes nothing, and on('error') hears that same error with action: 'pixel'. An ask() refused before it is sent, while another request is under way or for a template that does not offer Pixel, rejects with it too, but tells on('pixel') and on('error') nothing. The error says nothing of why, on purpose: show your customer one message that it did not work right now. You are told the reason instead: a limit or your credits running out raises a notification in the studio.

<div id="pixel" hidden>
<label for="pixel-prompt">Ask Pixel</label>
<input id="pixel-prompt" maxlength="2000" placeholder="Write my name in gold" />
<button id="pixel-ask" type="button">Ask</button>
<p id="pixel-status" role="status"></p>
<button id="pixel-undo" type="button" hidden>Undo</button>
</div>
const designer = await Pixonaut.mount('#canvas', {
publishableKey: 'pk_…',
templateId: 'name-sign@3',
showForm: false,
});
const box = document.querySelector('#pixel');
const prompt = document.querySelector('#pixel-prompt');
const ask = document.querySelector('#pixel-ask');
const status = document.querySelector('#pixel-status');
const undo = document.querySelector('#pixel-undo');
box.hidden = !designer.pixel.available();
designer.on('pixel', (event) => {
const busy = event.status === 'asking';
prompt.disabled = busy;
ask.disabled = busy;
undo.hidden = busy || !designer.pixel.canUndo();
if (event.status === 'asking') status.textContent = 'Pixel is working on it…';
if (event.status === 'done') status.textContent = event.reply;
if (event.status === 'undone') status.textContent = '';
});
ask.addEventListener('click', async () => {
try {
await designer.pixel.ask(prompt.value);
prompt.value = '';
} catch (error) {
if (!(error instanceof Pixonaut.PixelUnavailableError)) throw error;
status.textContent = "Pixel couldn't do that right now. Please try again.";
}
});
undo.addEventListener('click', () => designer.pixel.undo());

Pixel’s words in the built-in control follow the designer’s language, and you can change them with messages, as any of the designer’s words: the pixel.* keys.

Questions? Write to [email protected].

Status · Terms of service · Privacy policy · Subprocessors