PrismDraft SDK

Uploads

Two operations take a file instead of JSON: replacing an article's hero image, and adding the bytes of a knowledge source. For both, body is the file and contentType is required.

body is a Blob, an ArrayBuffer or a Uint8Array. A File is a Blob, and a Node Buffer is a Uint8Array, so both work. contentType is sent as the Content-Type header and tells the API how to read the bytes; the TypeScript type lists the values the operation accepts. Any other content type is refused by the API with 415.

An upload is a PUT, so it is never retried (see Retries and timeouts). The timer of timeoutMs runs while the file is sent; pass a larger init.timeoutMs for a big file.

Hero image

pd.articles.setHeroFromFile replaces the article's cover. It needs the images.update permission.

const image = await fetch("https://example.com/lamp.png");

const { asset } = await pd.articles.setHeroFromFile({
  articleId,
  altText: "A lamp on a desk",
  body: new Uint8Array(await image.arrayBuffer()),
  contentType: "image/png",
});
console.log(asset.publicUrl);
// In Node or Bun, the bytes of a file on disk work the same way:
const body = await readFile("lamp.png"); // a Buffer, which is a Uint8Array
  • Types: image/png, image/jpeg, image/webp, image/gif and image/avif.
  • Size: 25 MB at most; above that the API answers 413.
  • Bytes: they must decode as an image, or the API answers 400. The content type alone is not trusted.
  • altText is optional, 1 to 300 characters. Left out, the previous hero's alt text is kept, or the article's title if there was none.
  • The image is stored whole in the hero box and never cropped.
  • One hero per article. The new image replaces the old. If another replacement landed at the same moment the API answers 409 (CONFLICT); try again.
  • Quota. The new image must fit the workspace's storage quota, or the API answers 429 (QUOTA_EXCEEDED).
  • Webhook. image.regenerated is sent with type: "hero", and a published article also sends article.updated. See Webhooks.

To use a picture that is already on the web, let the API fetch it with pd.articles.setHeroFromUrl({ articleId, body: { imageUrl } }). It needs the same permission, sends the same webhook, takes 25 MB and 15 seconds at most, and refuses private network addresses.

Knowledge source file

A knowledge source holds material the AI can draw on. Adding a file is two calls: register the source, then upload its bytes. Both need the knowledge.create permission.

const { source } = await pd.knowledge.create({
  workspaceId,
  projectId,
  body: { type: "markdown", name: "Style notes" },
});

await pd.knowledge.uploadContent({
  workspaceId,
  sourceId: source.id,
  body: new Blob(["# Style notes\n\nShort sentences.\n"]),
  contentType: "text/markdown",
});

The source's type must match the file you upload:

Source type contentType
pdf application/pdf
docx application/vnd.openxmlformats-officedocument.wordprocessingml.document
txt text/plain
markdown text/markdown
  • Size: 10 MiB at most; above that the API answers 413.
  • Mismatch: a file whose type differs from the source's answers 400 (INVALID_REQUEST).
  • Empty body: answers 400.
  • Unknown source: 404 (RESOURCE_NOT_FOUND).
  • Ingestion runs in the background. The call returns the source; read status on pd.knowledge.list to follow it.

To run ingestion again, call pd.knowledge.reingest.

Images in an imported article

The body of an article is not uploaded. To import Markdown with images, send contentMarkdown to pd.articles.create: the API downloads each image the Markdown refers to. See Recipes.