The core API flow is asynchronous: create a job, poll until it finishes, create an export, then download before the export expires.
Create a job with an Idempotency-Key and store the returned job_id.
Poll the job every 2 to 5 seconds until status is done, failed, or cancelled.
Read the result, then create an export for the images you want to download.
Poll the export until it is done, then download before expires_at. If it expires, create a new export from the completed job.
Save the job id and retry create requests with an Idempotency-Key.
const baseUrl = 'https://imageextract.com'
const apiKey = process.env.IMAGEEXTRACT_API_KEY
async function request(path, options = {}) {
const response = await fetch(baseUrl + path, {
...options,
headers: {
Authorization: `Bearer ${apiKey}`,
...(options.headers ?? {}),
},
})
if (!response.ok) throw new Error(await response.text())
return response
}
async function sleep(ms) {
await new Promise((resolve) => setTimeout(resolve, ms))
}
const create = await request('/api/v1/jobs', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({ type: 'url', input: 'https://example.com' }),
}).then((response) => response.json())
let job
do {
await sleep(3000)
job = await request(`/api/v1/jobs/${create.job_id}`).then((response) => response.json())
} while (job.status === 'queued' || job.status === 'processing' || job.status === 'pending')
if (job.status !== 'done') throw new Error(job.error ?? 'Extraction failed')
const result = await request(`/api/v1/jobs/${create.job_id}/result`).then((response) => response.json())
const createdExport = await request(`/api/v1/jobs/${create.job_id}/exports`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ template: 'zip' }),
}).then((response) => response.json())
let exportStatus = createdExport
while (exportStatus.status === 'queued' || exportStatus.status === 'processing') {
await sleep(3000)
exportStatus = await request(`/api/v1/jobs/${create.job_id}/exports/${createdExport.id}`).then((response) => response.json())
}
if (exportStatus.status !== 'done') throw new Error(exportStatus.error ?? 'Export failed')
const zip = await request(`/api/v1/jobs/${create.job_id}/exports/${createdExport.id}/download`)
console.log({ images: result.image_count, expires_at: exportStatus.expires_at, bytes: Number(zip.headers.get('content-length') ?? 0) })