Skip to content
KismetKismetDevelopers
Beta accessllms.txt

Import images

View .md

Import images you are authorized to copy into your collection’s media library. This early-access operation family requires a matching API deployment and SDK. It does not publish content, activate routes, or change a site’s credentials.

With manager OAuth, preview import_collection_images using collection_slug and input containing a fresh UUID requestId and up to 50 unique urls (src and optional alt). Review the normalized plan, then confirm the same input with confirm: true and its exact planDigest. Collection ADMIN or MEMBER may import; scoped collection roles may inspect get_collection_media_import. Guest login is not editor authority.

Poll the returned job ID. Use resume_collection_media_import only to recover unfinished work: preview, review, then confirm. An active worker cannot be resumed concurrently. This workflow uses manager OAuth and does not require issuing a site server key.

Imports run asynchronously and may wait in a queue. A pending job is not evidence that downloading started. Interrupted processing resumes from settled source results; failed jobs wait for an explicit authorized resume. Inspect the returned status rather than assuming an accepted request has finished.

Use a restricted server secret with collection-wide media.import for plan/create/resume and independent media.read for progress. The methods are absent from the browser client.

import { createKismetClient } from '@kismet-tech/sdk/server';
import { randomUUID } from 'node:crypto';
const kismet = createKismetClient({ collection: 'example-stays',
apiKey: process.env.KISMET_SERVER_KEY!, baseUrl: 'https://api.ksmt.app/v1' });
const plan = await kismet.mediaImports.plan({ requestId: randomUUID(),
urls: [{ src: 'https://media.example.com/waterfront.jpg', alt: 'Waterfront path' }] });
// Show plan.input and warnings to the authorized editor before confirming.
const job = await kismet.mediaImports.create({ ...plan.input,
planDigest: plan.planDigest, confirm: true });
const progress = await kismet.mediaImports.get(job.id);
// Poll with backoff; completed can include failed sources.
for (const result of progress.results) {
if (result.status !== 'failed' && result.image) console.log(result.image.id, result.image.url);
}

REST uses POST /v1/developer/collections/{collection}/media/imports/plan, POST .../imports, GET .../imports/{id}, and POST .../imports/{id}/resume ({ "confirm": true }). Send the server credential in the Authorization header, never in a URL.

The shared importer does not store or serve SVG. For self-contained vector logos and illustrations, the SDK source/evaluation package includes media-converter, a separate server-side converter. It accepts bounded static geometry and simple local CSS/clipping, then emits PNG only. Scripts, external resources, entities, animation, embedded HTML, unsupported constructs, and cyclic references are rejected; nothing is silently removed except the supported CSS after applying it.

Build the converter from the supplied SDK package (Docker is required):

Terminal window
docker build -t kismet-media-converter ./node_modules/@kismet-tech/sdk/media-converter

Run it on one source file you are authorized to copy. Use an empty private output directory, absolute paths, and the full isolation profile:

Terminal window
docker run --rm --user "$(id -u):$(id -g)" \
--network=none --read-only --cap-drop=ALL --security-opt=no-new-privileges \
--pids-limit=64 --memory=256m --cpus=1 \
--tmpfs /tmp:rw,noexec,nosuid,size=16m \
--mount type=bind,source=/absolute/source.svg,target=/input.svg,readonly \
--mount type=bind,source=/absolute/empty-output,target=/output \
kismet-media-converter

Never pass production credentials, extra environment variables, or other private mounts to this container. The converter checks its runtime limits and refuses host, root, networked, writable-root, or unbounded execution. It caps source bytes at 512 KiB, normalized geometry at 2 MiB/4,096 nodes/32 levels, output sides at 2,048 pixels (up to 4× intrinsic size), and rendering at five seconds inside a 20-second process deadline. It does not overwrite an existing output.png. Retain its source/PNG SHA-256 receipt privately.

There is no local-file upload or arbitrary SVG-storage operation in this API. Serve the resulting PNG from your approved source host and use its HTTPS URL in the normal reviewed media-import request. Inspect the managed-library result before replacing a content binding. Keep the original source unchanged; if a vector uses unsupported features, obtain a reviewed raster export rather than relaxing validation. Retain the unchanged original, conversion receipt, PNG, import request UUID, returned image ID, and owned URL in a private durable audit record. The receipt links the original SVG checksum to the exact PNG checksum; it is not a server attestation of third-party rights. Keep it after the import job expires—Kismet does not retain the original SVG or a permanent conversion receipt in that job. Converting an image does not publish a page.

  • Planning writes nothing and is not a reachability or rights check. Creation requires the exact reviewed digest. Replay the identical request UUID to recover its job; changed input with that UUID is rejected.
  • Each source yields imported, existing, or failed. Only successful owned image URLs belong in subsequent Article drafts. A completed job is not proof every image imported. Retry failed sources in a separately reviewed new request.
  • Progress persists in the shared cache for 24 hours, including settled source results. Explicit resume skips those results. It is not a permanent receipt or a guarantee against cache data loss; retain your reviewed source-to-owned-URL mapping privately.
  • Four new jobs per collection per continuously refilled hour, at most 50 sources per job. Polling does not consume this job budget. Honor 429 and back off. Unavailable persistence refuses creation before image writes.
  • Only public HTTPS JPEG, PNG, WebP, or GIF sources are accepted. Every DNS lookup and redirect is checked against private networks; credentials are not forwarded. Downloads are bounded to 10 MiB and decoded images to 40 million pixels. SVG, mismatched bytes, broken sources, and unsafe redirects fail independently.
  • Source URL query strings can contain private access tokens. Do not put source URLs in public logs, browser state, or chat. The library preserves collection ownership and deduplicates image content; it does not grant rights to copy third-party media.

After reviewing the results, replace the appropriate hero/body URLs in an Article import plan, review the new immutable revision, and publish to staging only as a separate authorized action. Production publication is not part of this workflow.