JavaScript Examples

This page shows complete JavaScript examples for the external Davix H2I API.

Requests are processed by the H2I engine (PixLab) through the public external endpoints:

  • /v1/h2i
  • /v1/image
  • /v1/pdf
  • /v1/tools

External requests require API key authentication. Supported authentication methods are:

  • X-Api-Key
  • Authorization: Bearer <key>

Optional idempotency headers are also supported:

  • Idempotency-Key
  • X-Idempotency-Key

In production environments, API keys must be sent in headers. Body and query-string API key transport is rejected.

Setup #

These examples use JavaScript (Node.js) with built-in fetch, FormData, and Blob support.

const BASE = 'https://pixlab.davix.dev';
const API_KEY = '<YOUR_API_KEY>';

Authentication #

Use either of these patterns:

headers: {
'X-Api-Key': API_KEY
}

or

headers: {
'Authorization': `Bearer ${API_KEY}`
}

Optional idempotency #

All examples may also include:

'Idempotency-Key': 'your-request-id-001'

Valid idempotency keys:

  • length: 8 to 128
  • allowed characters: A-Z, a-z, 0-9, ., _, :, -

A valid key is echoed back by the server as the Idempotency-Key response header.

Notes about outputs #

  • /v1/h2i, /v1/image, and /v1/pdf return generated outputs and signed URLs.
  • /v1/tools returns structured JSON analysis results instead of generated file URLs.
  • Static output fetches for /h2i/*, /image/*, and /pdf/* are behind signed URL protection. /tools/* is signed when signed output mode is enabled.

Helper for file uploads #

The multipart examples below use a small helper for Node.js file uploads.

import { openAsBlob } from 'node:fs';async function fileBlob(path, type) {
return openAsBlob(path, { type });
}

Endpoint #

POST /v1/h2i

Supported actions:

  • image
  • pdf

Action #

action=image

Converts HTML into an image.

const response = await fetch(`${BASE}/v1/h2i`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'h2i-image-001',
'Content-Type': 'application/json'
},
body: JSON.stringify({
action: 'image',
html: '<div style="width:100%;height:100%;display:flex;align-items:center;justify-content:center">Hello</div>',
css: 'body{margin:0}',
width: 1200,
height: 1600,
format: 'jpeg'
})
});const data = await response.json();
console.log(data);

Parameters

  • action — required, must be image
  • html — required HTML string
  • css — optional CSS string
  • width — optional viewport width, default 1000
  • height — optional viewport height, default 1500
  • format — optional output format, default png; only jpeg produces JPEG, other values become PNG

Notes

  • If width * height exceeds the render pixel limit, the request fails with render_size_exceeded.

Action #

action=pdf

Converts HTML into a PDF.

const response = await fetch(`${BASE}/v1/h2i`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-001',
'Content-Type': 'application/json'
},
body: JSON.stringify({
action: 'pdf',
html: '<h1>Invoice</h1>',
css: 'body{font-family:sans-serif}',
width: 1000,
height: 1500,
pdfFormat: 'LETTER',
pdfLandscape: false,
pdfMargin: 24,
preferCSSPageSize: true,
scale: 1,
printMode: false,
printBackground: true
})
});const data = await response.json();
console.log(data);

Parameters

  • action — required, must be pdf
  • html — required HTML string
  • css — optional CSS string
  • width, height — optional viewport values
  • pdfFormat — optional, default A4; only LETTER maps to Letter
  • pdfLandscape — optional boolean, default false
  • pdfMargin — optional integer, default 24
  • preferCSSPageSize — optional boolean, default true
  • scale — optional numeric, default 1
  • printMode — optional boolean, default false
  • printBackground — optional boolean, default true

Endpoint #

POST /v1/image

Supported actions:

  • format
  • resize
  • crop
  • transform
  • compress
  • enhance
  • padding
  • frame
  • background
  • watermark
  • pdf
  • metadata
  • multitask

The endpoint uses multipart/form-data.

Shared image parameters #

These parameters are reused across image actions:

  • action
  • images
  • watermarkImage
  • format
  • width, height, enlarge
  • cropX, cropY, cropWidth, cropHeight
  • rotate, flipH, flipV
  • targetSizeKB, quality
  • keepMetadata, normalizeOrientation
  • blur, sharpen, grayscale, sepia
  • brightness, contrast, saturation
  • pad, padTop, padRight, padBottom, padLeft, padColor
  • border, borderColor, borderRadius
  • backgroundColor, backgroundBlur
  • watermarkText, watermarkFontSize, watermarkColor, watermarkOpacity, watermarkPosition, watermarkMargin, watermarkScale
  • pdfMode, pdfPageSize, pdfOrientation, pdfMargin, pdfEmbedFormat, pdfJpegQuality
  • colorSpace
  • includeRawExif

Action #

action=format

const form = new FormData();
form.append('action', 'format');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('format', 'webp');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-002'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=resize

const form = new FormData();
form.append('action', 'resize');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('width', '1024');
form.append('height', '768');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-003'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=crop

const form = new FormData();
form.append('action', 'crop');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('cropX', '0');
form.append('cropY', '0');
form.append('cropWidth', '800');
form.append('cropHeight', '600');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-004'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=transform

const form = new FormData();
form.append('action', 'transform');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('rotate', '90');
form.append('flipH', 'true');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-005'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=compress

const form = new FormData();
form.append('action', 'compress');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('targetSizeKB', '200');
form.append('quality', '80');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-006'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=enhance

const form = new FormData();
form.append('action', 'enhance');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('sharpen', '1');
form.append('contrast', '1.1');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-007'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=padding

const form = new FormData();
form.append('action', 'padding');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('pad', '20');
form.append('padColor', '#ffffff');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-008'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=frame

const form = new FormData();
form.append('action', 'frame');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('border', '4');
form.append('borderColor', '#000000');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-009'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=background

const form = new FormData();
form.append('action', 'background');
form.append('images', await fileBlob('./samples/a.png', 'image/png'), 'a.png');
form.append('backgroundColor', '#ffffff');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-010'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=watermark

const form = new FormData();
form.append('action', 'watermark');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('watermarkText', 'H2I');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-011'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=pdf

const form = new FormData();
form.append('action', 'pdf');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('format', 'pdf');
form.append('pdfMode', 'single');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-012'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=metadata

const form = new FormData();
form.append('action', 'metadata');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('normalizeOrientation', 'true');
form.append('includeRawExif', 'true');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-013'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=multitask

const form = new FormData();
form.append('action', 'multitask');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('width', '1200');
form.append('format', 'webp');
form.append('watermarkText', 'H2I');const response = await fetch(`${BASE}/v1/image`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-014'
},
body: form
});const data = await response.json();
console.log(data);

For /v1/image:

  • metadata returns JSON metadata results
  • other actions return generated-file results with signed URLs under /image/<file>

Endpoint #

POST /v1/pdf

Supported actions:

  • merge
  • to-images
  • compress
  • extract-images
  • watermark
  • rotate
  • metadata
  • reorder
  • delete-pages
  • extract
  • flatten
  • encrypt
  • decrypt
  • split

The endpoint uses multipart/form-data. One optional watermarkImage upload is accepted, and for non-merge actions the first uploaded PDF is used as the primary input.

Shared PDF parameters #

  • action
  • files
  • sortByName
  • pages
  • format
  • quality
  • density
  • watermarkText
  • watermarkImage
  • opacity
  • position
  • fontSize
  • color
  • x
  • y
  • degrees
  • order
  • password
  • userPassword
  • ownerPassword
  • ranges
  • prefix

Action #

action=merge

const form = new FormData();
form.append('action', 'merge');
form.append('files', await fileBlob('./samples/one.pdf', 'application/pdf'), 'one.pdf');
form.append('files', await fileBlob('./samples/two.pdf', 'application/pdf'), 'two.pdf');
form.append('sortByName', 'true');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-015'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=to-images

const form = new FormData();
form.append('action', 'to-images');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');
form.append('pages', 'all');
form.append('format', 'png');
form.append('density', '144');
form.append('quality', '85');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-016'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=compress

const form = new FormData();
form.append('action', 'compress');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-017'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=extract-images

const form = new FormData();
form.append('action', 'extract-images');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');
form.append('pages', 'all');
form.append('imageFormat', 'jpeg');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-018'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=watermark

const form = new FormData();
form.append('action', 'watermark');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');
form.append('watermarkText', 'CONFIDENTIAL');
form.append('opacity', '0.3');
form.append('position', 'center');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-019'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=rotate

const form = new FormData();
form.append('action', 'rotate');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');
form.append('degrees', '90');
form.append('pages', '1,2');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-020'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=metadata

const form = new FormData();
form.append('action', 'metadata');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');
form.append('title', 'Updated');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-021'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=reorder

const form = new FormData();
form.append('action', 'reorder');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');
form.append('order', '[3,1,2]');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-022'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=delete-pages

const form = new FormData();
form.append('action', 'delete-pages');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');
form.append('pages', '2-4');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-023'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=extract

const form = new FormData();
form.append('action', 'extract');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');
form.append('pages', '1-3');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-024'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=flatten

const form = new FormData();
form.append('action', 'flatten');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-025'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=encrypt

const form = new FormData();
form.append('action', 'encrypt');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');
form.append('userPassword', 'userpass');
form.append('ownerPassword', 'ownerpass');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-026'
},
body: form
});const data = await response.json();
console.log(data);

userPassword is required for encrypt. ownerPassword is optional and defaults to userPassword if omitted. encrypt and decrypt depend on qpdf being available in the runtime environment.

Action #

action=decrypt

const form = new FormData();
form.append('action', 'decrypt');
form.append('files', await fileBlob('./samples/locked.pdf', 'application/pdf'), 'locked.pdf');
form.append('password', 'userpass');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-027'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=split

const form = new FormData();
form.append('action', 'split');
form.append('files', await fileBlob('./samples/doc.pdf', 'application/pdf'), 'doc.pdf');
form.append('ranges', '1-2,3-5');
form.append('prefix', 'chapter_');const response = await fetch(`${BASE}/v1/pdf`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-028'
},
body: form
});const data = await response.json();
console.log(data);

For /v1/pdf:

  • pages accepts selectors such as all, first, and CSV page ranges
  • ranges is required for split
  • password is required for decrypt
  • userPassword is required for encrypt
  • errors can include pdf_page_limit_exceeded for page-limited operations

Endpoint #

POST /v1/tools

Top-level action values are single and multitask, but analyzer selection is controlled through tools or tools[].

Documented tool names:

  • metadata
  • colors
  • detect-format
  • orientation
  • hash
  • similarity
  • dimensions
  • quality
  • transparency
  • efficiency

Shared tools parameters #

  • action
  • images
  • tools or tools[]
  • includeRawExif
  • paletteSize
  • hashType
  • qualitySample
  • transparencySample
  • similarityMode
  • similarityThreshold
  • efficiencyFormat
  • efficiencyQuality

Tool #

metadata

const form = new FormData();
form.append('action', 'single');
form.append('tools', 'metadata');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('includeRawExif', 'true');const response = await fetch(`${BASE}/v1/tools`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-029'
},
body: form
});const data = await response.json();
console.log(data);

Tool #

colors

const form = new FormData();
form.append('action', 'single');
form.append('tools', 'colors');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('paletteSize', '8');const response = await fetch(`${BASE}/v1/tools`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-030'
},
body: form
});const data = await response.json();
console.log(data);

Tool #

detect-format

const form = new FormData();
form.append('action', 'single');
form.append('tools', 'detect-format');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');const response = await fetch(`${BASE}/v1/tools`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-031'
},
body: form
});const data = await response.json();
console.log(data);

Tool #

orientation

const form = new FormData();
form.append('action', 'single');
form.append('tools', 'orientation');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');const response = await fetch(`${BASE}/v1/tools`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-032'
},
body: form
});const data = await response.json();
console.log(data);

Tool #

hash

const form = new FormData();
form.append('action', 'single');
form.append('tools', 'hash');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('hashType', 'phash');const response = await fetch(`${BASE}/v1/tools`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-033'
},
body: form
});const data = await response.json();
console.log(data);

Tool #

similarity

const form = new FormData();
form.append('action', 'single');
form.append('tools', 'similarity');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('images', await fileBlob('./samples/b.jpg', 'image/jpeg'), 'b.jpg');
form.append('similarityMode', 'tofirst');
form.append('similarityThreshold', '8');const response = await fetch(`${BASE}/v1/tools`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-034'
},
body: form
});const data = await response.json();
console.log(data);

Tool #

dimensions

const form = new FormData();
form.append('action', 'single');
form.append('tools', 'dimensions');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');const response = await fetch(`${BASE}/v1/tools`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-035'
},
body: form
});const data = await response.json();
console.log(data);

Tool #

transparency

const form = new FormData();
form.append('action', 'single');
form.append('tools', 'transparency');
form.append('images', await fileBlob('./samples/a.png', 'image/png'), 'a.png');
form.append('transparencySample', '64');const response = await fetch(`${BASE}/v1/tools`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-036'
},
body: form
});const data = await response.json();
console.log(data);

Tool #

quality

const form = new FormData();
form.append('action', 'single');
form.append('tools', 'quality');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('qualitySample', '256');const response = await fetch(`${BASE}/v1/tools`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-037'
},
body: form
});const data = await response.json();
console.log(data);

Tool #

efficiency

const form = new FormData();
form.append('action', 'single');
form.append('tools', 'efficiency');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('efficiencyFormat', 'webp');
form.append('efficiencyQuality', '80');const response = await fetch(`${BASE}/v1/tools`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-038'
},
body: form
});const data = await response.json();
console.log(data);

Action #

action=multitask

const form = new FormData();
form.append('action', 'multitask');
form.append('tools', 'metadata,dimensions,hash,similarity,quality');
form.append('images', await fileBlob('./samples/a.jpg', 'image/jpeg'), 'a.jpg');
form.append('images', await fileBlob('./samples/b.jpg', 'image/jpeg'), 'b.jpg');
form.append('hashType', 'phash');
form.append('similarityMode', 'tofirst');
form.append('similarityThreshold', '10');
form.append('qualitySample', '256');const response = await fetch(`${BASE}/v1/tools`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Idempotency-Key': 'idem-ext-039'
},
body: form
});const data = await response.json();
console.log(data);

Notes

  • action=single requires exactly one tool.
  • tools and tools[] are both accepted.
  • Tool names are parsed as lowercase list values.
  • similarityMode supports pairs and tofirst.
  • The multitask request format is flat multipart form-data. There is no nested tasks[] JSON structure in the documented implementation.

Tools response shape #

/v1/tools returns structured analysis results in this form:

{
results: [
{
originalName: 'a.jpg',
sizeBytes: 123456,
tools: {}
}
],
request_id: 'req_abc123'
}

Similarity can also add similarity-specific structures depending on mode.


Common external errors #

These are the main external error codes relevant to JavaScript usage:

  • api_key_location_not_allowed
  • invalid_api_key
  • key_expired
  • endpoint_not_allowed
  • rate_limit_exceeded
  • rate_limit_store_unavailable
  • timeout
  • server_busy
  • file_too_large
  • too_many_files
  • total_upload_exceeded
  • dimension_exceeded
  • invalid_upload
  • unsupported_media_type
  • monthly_quota_exceeded
  • invalid_parameter
  • missing_field
  • html_too_large
  • render_size_exceeded
  • html_render_failed
  • image_processing_failed
  • pdf_tool_failed
  • tool_processing_failed

Final notes #

  • /v1/h2i uses JSON request bodies.
  • /v1/image, /v1/pdf, and /v1/tools use multipart/form-data.
  • /v1/tools returns JSON analysis results rather than generated file URLs.
  • encrypt and decrypt depend on qpdf being available in the runtime environment.
  • Generated output URLs are signed and protected for output-fetch paths according to the configured signed URL behavior.
Was it helpful ?
Scroll to Top