inklet docs

Contents

The Content resource — the lower-level lifecycle behind inklet.push, including create, confirm, and upload ticket refresh.

A Content is one submission: a set of assets plus your intent. Most applications should use inklet.push.*, which drives this resource for you. Reach for it directly when you need to control the individual calls.

retrieve()

const content = await inklet.contents.retrieve("content_123");

The main use is polling after a push.

list()

const page = await inklet.contents.list({ mode: "manual", state: "ready" });
list(options?: ListContentsOptions): Promise<ContentPage>

Prop

Type

An out-of-range value for state or mode throws ConfigurationError locally.

create()

create(input: CreateContentRequest, idempotencyKey: string): Promise<CreateContentResponse>

Prop

Type

Note the asset shape here differs from inklet.assets.*. Binary assets are declared by metadata onlyfilename, contentType, sizeBytes — because the bytes go to a presigned URL afterwards, not in this request body.

type CreateContentAssetInput =
  | { type: "text"; text: string }
  | { type: "link"; url: string }
  | { type: "image"; filename: string; contentType: AllowedImageContentType; sizeBytes: number }
  | { type: "file"; filename: string; contentType: AllowedFileContentType; sizeBytes: number };

Returns the Content plus one upload ticket per binary asset:

Prop

Type

Prop

Type

idempotencyKey is required here — 8–128 printable ASCII characters, no spaces. It is sent as the idempotency-key header.

The service applies the same plan authorization at this lower level: auto and manual require Pro, while hardcode is available on Free. Direct use of contents.create() cannot bypass the AI feature gate.

Validation

Enforced locally, before the request:

FieldRule
modeMust be one of the three modes
displayIdRequired for manual/hardcode; must be omitted for auto
assets1–50 entries
Hardcode assetsExactly one asset, and it must be a PNG or JPEG image
sizeBytesInteger, 1 to 10 MiB
Link URLsAbsolute HTTP(S), no embedded credentials
TextAt least one non-whitespace character

confirm()

Closes uploads and starts processing:

const content = await inklet.contents.confirm(content.id);

Check content.upload.status afterwards:

StatusMeaning
awaiting_uploadNothing uploaded yet
partialSome assets missing — upload.failedAssetIndexes lists them
completeAll assets present

refreshUploadTickets()

New presigned URLs for assets that failed to upload:

const refreshed = await inklet.contents.refreshUploadTickets(content.id, [0, 2]);

assetIndexes must be one or more unique non-negative integers; anything else throws ConfigurationError. Returns the same shape as create().

The Content type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

warnings is worth logging even on success — it is where inklet reports things like a link it could not fetch, or a display it skipped.

Doing it by hand

The full sequence push.* performs, if you need to own each step:

const created = await inklet.contents.create(
  {
    mode: "manual",
    displayId: "display_123",
    title: "Menu",
    assets: [
      { type: "text", text: "Tonight" },
      {
        type: "file",
        filename: "menu.pdf",
        contentType: "application/pdf",
        sizeBytes: bytes.byteLength,
      },
    ],
  },
  "menu-2026-08-15",
);

for (const ticket of created.uploadTickets) {
  const form = new FormData();
  for (const [key, value] of Object.entries(ticket.fields)) {
    form.append(key, value);
  }
  form.append("file", new Blob([bytes], { type: "application/pdf" }), "menu.pdf");

  await fetch(ticket.url, { method: "POST", body: form });
}

const content = await inklet.contents.confirm(created.content.id);

Note the upload fetch above carries no inklet credentials — that is deliberate, and push.* does the same. Never attach your PAT to a storage URL.

On this page