{"_id":"@api2convert/sdk","_rev":"6-29073610b9607045baae1f039a417d78","name":"@api2convert/sdk","dist-tags":{"latest":"10.4.1"},"versions":{"10.2.0":{"name":"@api2convert/sdk","version":"10.2.0","keywords":["api2convert","file conversion","convert","pdf","image","video","audio","ocr","sdk","api"],"author":{"name":"Qaamgo Media GmbH"},"license":"MIT","_id":"@api2convert/sdk@10.2.0","maintainers":[{"name":"api2convert","email":"time2talk@api2convert.com"}],"homepage":"https://www.api2convert.com","bugs":{"url":"https://github.com/QaamGo/api2convert-nodejs/issues"},"dist":{"shasum":"456fdfab484ebcade8f172bb7dceb68b2764ee0f","tarball":"https://registry.npmjs.org/@api2convert/sdk/-/sdk-10.2.0.tgz","fileCount":14,"integrity":"sha512-gRb3mSExOS+z7VkUvcF27qlV3Kzv3RaeuDfRAJ1bxPm7vi3FZSHyIh2Af7D1Fk8mhKhZKyN6o8jZ29ip+NYE5g==","signatures":[{"sig":"MEUCIBQRuadDS3kfa2tWLy8uLp5b4ziHBX22b0itaSh5gktfAiEA1KgeQTWdV6DtRntwSetxAJ5KVGlb3kNExPuWu4vOOPs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":486576},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"gitHead":"73c4fe0c0135dd90bfeaae9febde6fe0b0463306","scripts":{"lint":"eslint . && prettier --check .","test":"vitest run test/unit","audit":"npm audit --omit=dev --audit-level=high","build":"tsup","check":"npm run lint && npm run typecheck && npm run test && npm run test:security && npm run audit","lint:fix":"eslint . --fix && prettier --write .","test:live":"vitest run test/live","typecheck":"tsc --noEmit","test:security":"vitest run test/security","prepublishOnly":"npm run check && npm run build"},"_npmUser":{"name":"api2convert","email":"time2talk@api2convert.com"},"repository":{"url":"git+https://github.com/QaamGo/api2convert-nodejs.git","type":"git"},"_npmVersion":"11.6.2","description":"Official Node.js/TypeScript SDK for the API2Convert file-conversion API. Convert, compress and transform images, documents, audio, video, ebooks, archives and CAD with one line of code.","directories":{},"sideEffects":false,"_nodeVersion":"24.11.1","dependencies":{},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","eslint":"^9","vitest":"^2","prettier":"^3","@eslint/js":"^9","typescript":"^5.6","@types/node":"^22","typescript-eslint":"^8","@vitest/coverage-v8":"^2"},"_npmOperationalInternal":{"tmp":"tmp/sdk_10.2.0_1783355987405_0.7096486709397962","host":"s3://npm-registry-packages-npm-production"}},"10.2.1":{"name":"@api2convert/sdk","version":"10.2.1","keywords":["api2convert","file conversion","convert","pdf","image","video","audio","ocr","sdk","api"],"author":{"name":"Qaamgo Media GmbH"},"license":"MIT","_id":"@api2convert/sdk@10.2.1","maintainers":[{"name":"api2convert","email":"time2talk@api2convert.com"}],"homepage":"https://www.api2convert.com","bugs":{"url":"https://github.com/QaamGo/api2convert-nodejs/issues"},"dist":{"shasum":"5ac45e467b83075f90016514c91855c93f0de91f","tarball":"https://registry.npmjs.org/@api2convert/sdk/-/sdk-10.2.1.tgz","fileCount":14,"integrity":"sha512-oEDCWqRNW0+IwC8QL/BGo306myBMzeyBINYke5tc4PTAIbg3z0iKnqTzqVXCkJNbL6+rZBaStle9E9M8tDNMsw==","signatures":[{"sig":"MEYCIQD156DVZnNNO9WlNvAJfbQ+LqKaUx1NOv7013C3pEANVwIhAJQUWChjvTlkTFgGEFwA3gvukXjwgkwTWsS5CZKB8eW7","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@api2convert%2fsdk@10.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":490351},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"gitHead":"3234c3946b9b3afa999b27f2b129595a0eec3120","scripts":{"lint":"eslint . && prettier --check .","test":"vitest run test/unit","audit":"npm audit --omit=dev --audit-level=high","build":"tsup","check":"npm run lint && npm run typecheck && npm run test && npm run test:security && npm run audit","lint:fix":"eslint . --fix && prettier --write .","test:live":"vitest run test/live","typecheck":"tsc --noEmit","test:security":"vitest run test/security","prepublishOnly":"npm run check && npm run build"},"_npmUser":{"name":"api2convert","email":"time2talk@api2convert.com"},"repository":{"url":"git+https://github.com/QaamGo/api2convert-nodejs.git","type":"git"},"_npmVersion":"10.9.8","description":"Official Node.js/TypeScript SDK for the API2Convert file-conversion API. Convert, compress and transform images, documents, audio, video, ebooks, archives and CAD with one line of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","dependencies":{},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","eslint":"^9","vitest":"^2","prettier":"^3","@eslint/js":"^9","typescript":"^5.6","@types/node":"^22","typescript-eslint":"^8","@vitest/coverage-v8":"^2"},"_npmOperationalInternal":{"tmp":"tmp/sdk_10.2.1_1783523548231_0.9835095317857163","host":"s3://npm-registry-packages-npm-production"}},"10.3.0":{"name":"@api2convert/sdk","version":"10.3.0","keywords":["api2convert","file conversion","convert","pdf","image","video","audio","ocr","sdk","api"],"author":{"name":"Qaamgo Media GmbH"},"license":"MIT","_id":"@api2convert/sdk@10.3.0","maintainers":[{"name":"api2convert","email":"time2talk@api2convert.com"}],"homepage":"https://www.api2convert.com","bugs":{"url":"https://github.com/QaamGo/api2convert-nodejs/issues"},"dist":{"shasum":"37ab64e0a8a6178b38bae725e2571a0db3553b98","tarball":"https://registry.npmjs.org/@api2convert/sdk/-/sdk-10.3.0.tgz","fileCount":14,"integrity":"sha512-tv953Ilq6h1IVP131GrjTrn1bWvnjNqPLjQIF2XogKMAMq2+R8m1Vz17HxHBSnF9J4/q8DuFuQvnx3NsUBG2+Q==","signatures":[{"sig":"MEQCIHNiZrXxDTY2xnPBDWGCi4P41gVZu7X6DXx2rrpen+7gAiAEfYFCc6F2xg9Q+S6Zkz1y2GraBLl/E/7XPIUKosnxeg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@api2convert%2fsdk@10.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":581732},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"gitHead":"5b187adbcd19bef04957f6d7794bfe09b4c51d4d","scripts":{"lint":"eslint . && prettier --check .","test":"vitest run test/unit","audit":"npm audit --omit=dev --audit-level=high","build":"tsup","check":"npm run lint && npm run typecheck && npm run test && npm run test:security && npm run audit","lint:fix":"eslint . --fix && prettier --write .","test:live":"vitest run test/live","typecheck":"tsc --noEmit","test:security":"vitest run test/security","prepublishOnly":"npm run check && npm run build"},"_npmUser":{"name":"api2convert","email":"time2talk@api2convert.com"},"repository":{"url":"git+https://github.com/QaamGo/api2convert-nodejs.git","type":"git"},"_npmVersion":"10.9.8","description":"Official Node.js/TypeScript SDK for the API2Convert file-conversion API. Convert, compress and transform images, documents, audio, video, ebooks, archives and CAD with one line of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","dependencies":{},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","eslint":"^9","vitest":"^2","prettier":"^3","@eslint/js":"^9","typescript":"^5.6","@types/node":"^22","typescript-eslint":"^8","@vitest/coverage-v8":"^2"},"_npmOperationalInternal":{"tmp":"tmp/sdk_10.3.0_1783858841308_0.3933866090075282","host":"s3://npm-registry-packages-npm-production"}},"10.3.1":{"name":"@api2convert/sdk","version":"10.3.1","keywords":["api2convert","file conversion","convert","pdf","image","video","audio","ocr","sdk","api"],"author":{"name":"Qaamgo Media GmbH"},"license":"MIT","_id":"@api2convert/sdk@10.3.1","maintainers":[{"name":"api2convert","email":"time2talk@api2convert.com"}],"homepage":"https://www.api2convert.com","bugs":{"url":"https://github.com/QaamGo/api2convert-nodejs/issues"},"dist":{"shasum":"d2f53e356d7cf48ea9cf70862573dc1022c589d4","tarball":"https://registry.npmjs.org/@api2convert/sdk/-/sdk-10.3.1.tgz","fileCount":14,"integrity":"sha512-GvR33TdI2bqnIMlGexG3zDTNMJHWwTk68y8+ijfOlSONNgiPBG0dUUT8g+/1UtarfRb+SHgN3QBD9ARcoJJBsQ==","signatures":[{"sig":"MEQCIHZ9O4UkeJbDns3BEJqCOPMd/adK4zGsqZuURKkG7YEEAiACw75jZX1uhGhIPem/Qyyq5Yn6LoApu0q1M4/bXD3MYw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@api2convert%2fsdk@10.3.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":583142},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"gitHead":"1a92b600e1a5f85f07faed2b3aae51b3a89732b1","scripts":{"lint":"eslint . && prettier --check .","test":"vitest run test/unit","audit":"npm audit --omit=dev --audit-level=high","build":"tsup","check":"npm run lint && npm run typecheck && npm run test && npm run test:security && npm run audit","lint:fix":"eslint . --fix && prettier --write .","test:live":"vitest run test/live","typecheck":"tsc --noEmit","test:security":"vitest run test/security","prepublishOnly":"npm run check && npm run build"},"_npmUser":{"name":"api2convert","email":"time2talk@api2convert.com"},"repository":{"url":"git+https://github.com/QaamGo/api2convert-nodejs.git","type":"git"},"_npmVersion":"10.9.8","description":"Official Node.js/TypeScript SDK for the API2Convert file-conversion API. Convert, compress and transform images, documents, audio, video, ebooks, archives and CAD with one line of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","dependencies":{},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","eslint":"^9","vitest":"^2","prettier":"^3","@eslint/js":"^9","typescript":"^5.6","@types/node":"^22","typescript-eslint":"^8","@vitest/coverage-v8":"^2"},"_npmOperationalInternal":{"tmp":"tmp/sdk_10.3.1_1783869106603_0.9404489648096972","host":"s3://npm-registry-packages-npm-production"}},"10.4.0":{"name":"@api2convert/sdk","version":"10.4.0","keywords":["api2convert","file conversion","convert","pdf","image","video","audio","ocr","sdk","api"],"author":{"name":"Qaamgo Media GmbH"},"license":"MIT","_id":"@api2convert/sdk@10.4.0","maintainers":[{"name":"api2convert","email":"time2talk@api2convert.com"}],"homepage":"https://www.api2convert.com","bugs":{"url":"https://github.com/QaamGo/api2convert-nodejs/issues"},"dist":{"shasum":"9af389efd7cb20166a51d071178ce99afa52faf2","tarball":"https://registry.npmjs.org/@api2convert/sdk/-/sdk-10.4.0.tgz","fileCount":14,"integrity":"sha512-o+dPHoCRqViD5TcO+bNsCldhGPAh0kGwlFoQOn2ELauBdS2dL9IoqDAo2a053C+Fib3LYZielNppFTXSwy/8yQ==","signatures":[{"sig":"MEUCIGN5gdUZKVi25ObzyJV1Ns2AXHPiFgPbdyKTF3Kvlse6AiEAunnpy2PxIfBg0Z8zjBtHzoPnL2ktbaMMDP/dnZJ8Rqo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@api2convert%2fsdk@10.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":585039},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"gitHead":"fccb46e8e78e2553cf72360ec5e4b68dfda3a34f","scripts":{"lint":"eslint . && prettier --check .","test":"vitest run test/unit","audit":"npm audit --omit=dev --audit-level=high","build":"tsup","check":"npm run lint && npm run typecheck && npm run test && npm run test:security && npm run audit","lint:fix":"eslint . --fix && prettier --write .","test:live":"vitest run test/live","typecheck":"tsc --noEmit","test:security":"vitest run test/security","prepublishOnly":"npm run check && npm run build"},"_npmUser":{"name":"api2convert","email":"time2talk@api2convert.com"},"repository":{"url":"git+https://github.com/QaamGo/api2convert-nodejs.git","type":"git"},"_npmVersion":"10.9.8","description":"Official Node.js/TypeScript SDK for the API2Convert file-conversion API. Convert, compress and transform images, documents, audio, video, ebooks, archives and CAD with one line of code.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","eslint":"^10.8.0","vitest":"^4.1.10","prettier":"^3","@eslint/js":"^10.0.1","typescript":"^5.9.3","@types/node":"^26.1.2","typescript-eslint":"^8","@vitest/coverage-v8":"^4.1.10"},"_npmOperationalInternal":{"tmp":"tmp/sdk_10.4.0_1786112444556_0.8944668773478808","host":"s3://npm-registry-packages-npm-production"}},"10.4.1":{"name":"@api2convert/sdk","version":"10.4.1","description":"Official Node.js/TypeScript SDK for the API2Convert file-conversion API. Convert, compress and transform images, documents, audio, video, ebooks, archives and CAD with one line of code.","keywords":["api2convert","file conversion","convert","pdf","image","video","audio","ocr","sdk","api"],"homepage":"https://www.api2convert.com","license":"MIT","author":{"name":"Qaamgo Media GmbH"},"repository":{"type":"git","url":"git+https://github.com/QaamGo/api2convert-nodejs.git"},"bugs":{"url":"https://github.com/QaamGo/api2convert-nodejs/issues"},"type":"module","engines":{"node":">=20"},"sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"scripts":{"build":"tsup","typecheck":"tsc --noEmit","lint":"eslint . && prettier --check .","lint:fix":"eslint . --fix && prettier --write .","test":"vitest run test/unit","test:security":"vitest run test/security","test:live":"vitest run test/live","audit":"npm audit --omit=dev --audit-level=high","check":"npm run lint && npm run typecheck && npm run test && npm run test:security && npm run audit","prepublishOnly":"npm run check && npm run build"},"overrides":{"esbuild":"^0.28.1"},"devDependencies":{"@eslint/js":"^10.0.1","@types/node":"^26.1.2","@vitest/coverage-v8":"^4.1.10","eslint":"^10.8.0","prettier":"^3","tsup":"^8","typescript":"^5.9.3","typescript-eslint":"^8","vitest":"^4.1.10"},"publishConfig":{"access":"public","provenance":true},"_id":"@api2convert/sdk@10.4.1","gitHead":"5a8d92066c19cf319c1b7323cd866626984c8ea0","_nodeVersion":"22.23.2","_npmVersion":"10.9.8","dist":{"integrity":"sha512-VSWsGGKEO6OLCGeBW/C5bh78YDamgOfdMPrweuc3/LLmXnMOYN0iNFCmz6xWlFh4E4QD8YWuzUtRXINK5roo2g==","shasum":"c35356e6b9a9156c3f18f8eac2756fb6b8e16625","tarball":"https://registry.npmjs.org/@api2convert/sdk/-/sdk-10.4.1.tgz","fileCount":14,"unpackedSize":589269,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@api2convert%2fsdk@10.4.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIA5xa7jvkDZuPsfSn2hcuzbBX4nQOzyLRT/2sRZlrzQuAiBZ4hVdVR+enymRYFsMgtSnULZ8PQh/Lf+FwceYU3Kt7A=="}]},"_npmUser":{"name":"api2convert","email":"time2talk@api2convert.com"},"directories":{},"maintainers":[{"name":"api2convert","email":"time2talk@api2convert.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_10.4.1_1786533173292_0.7263292217001558"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-06T16:39:47.092Z","modified":"2026-08-12T11:12:53.779Z","10.2.0":"2026-07-06T16:39:47.549Z","10.2.1":"2026-07-08T15:12:28.407Z","10.3.0":"2026-07-12T12:20:41.491Z","10.3.1":"2026-07-12T15:11:46.754Z","10.4.0":"2026-08-07T14:20:44.705Z","10.4.1":"2026-08-12T11:12:53.451Z"},"bugs":{"url":"https://github.com/QaamGo/api2convert-nodejs/issues"},"author":{"name":"Qaamgo Media GmbH"},"license":"MIT","homepage":"https://www.api2convert.com","keywords":["api2convert","file conversion","convert","pdf","image","video","audio","ocr","sdk","api"],"repository":{"type":"git","url":"git+https://github.com/QaamGo/api2convert-nodejs.git"},"description":"Official Node.js/TypeScript SDK for the API2Convert file-conversion API. Convert, compress and transform images, documents, audio, video, ebooks, archives and CAD with one line of code.","maintainers":[{"name":"api2convert","email":"time2talk@api2convert.com"}],"readme":"# API2Convert Node.js SDK\n\n[![CI](https://github.com/QaamGo/api2convert-nodejs/actions/workflows/ci.yml/badge.svg)](https://github.com/QaamGo/api2convert-nodejs/actions/workflows/ci.yml)\n[![npm](https://img.shields.io/npm/v/@api2convert/sdk)](https://www.npmjs.com/package/@api2convert/sdk)\n![Node](https://img.shields.io/badge/node-%E2%89%A5%2018-brightgreen)\n![License](https://img.shields.io/badge/license-MIT-green)\n\nThe official Node.js/TypeScript client for the [API2Convert](https://www.api2convert.com)\nfile-conversion API. Convert, compress and transform **images, documents, audio, video, ebooks,\narchives and CAD** — and run operations like OCR, merge, thumbnail and website capture — in one line\nof code.\n\n```ts\nimport { Api2Convert } from '@api2convert/sdk';\n\nconst client = new Api2Convert('YOUR_API_KEY');\n\nconst result = await client.convert('invoice.docx', 'pdf');\nawait result.save('invoice.pdf');\n```\n\nThat single call creates a job, uploads your file, starts it, waits for it to finish and gives you\nback a result you can save. No polling loops, no manual upload handling.\n\n## Requirements\n\n- Node.js 18+ (uses the built-in global `fetch`, `Blob`, `FormData` and `crypto`).\n- **Zero runtime dependencies.** The HTTP layer is the platform `fetch` (undici); HMAC uses\n  `node:crypto`. Ships as dual **ESM + CommonJS** with TypeScript types.\n\n## Install\n\n```bash\nnpm install @api2convert/sdk\n```\n\nGet an API key from the [API2Convert dashboard / documentation](https://www.api2convert.com/documentation).\n\n## Quick start\n\n```ts\nimport { Api2Convert } from '@api2convert/sdk';\n\n// Reads the API2CONVERT_API_KEY environment variable when no key is passed.\nconst client = new Api2Convert('YOUR_API_KEY');\n\n// 1) From a local file\nawait (await client.convert('photo.png', 'jpg')).save('photo.jpg');\n\n// 2) From a URL\nawait (await client.convert('https://example.com/photo.png', 'jpg')).save('photo.jpg');\n\n// 3) With conversion options (discover them via client.options('jpg'))\nconst result = await client.convert('photo.png', 'jpg', { quality: 85, width: 1280, height: 720 });\nawait result.save('out/'); // the processed-file directory\n```\n\n`convert(input, to, options?, opts?)` — `input` is a **local path string, a public URL, a\n`Uint8Array`/`Buffer`, a Node `Readable`, or a web `ReadableStream`**; `to` is the **target format**;\n`options` are the **conversion options** for that target. Less-common controls live on the `opts`\nobject (so they can never collide with an open-ended API option): `category`, `timeout`,\n`outputIndex`, `filename`, `downloadPassword`. The returned `ConversionResult` lets you:\n\n```ts\nconst result = await client.convert('report.docx', 'pdf');\n\nawait result.save('report.pdf'); // stream to a file\nawait result.save('downloads/'); // ...or a directory (keeps the server filename)\nconst bytes = await result.contents(); // ...or get the raw Buffer\nconst url = result.url(); // ...or just the download URL\n```\n\n## Password-protect the result\n\nPass a `downloadPassword` and the output is locked behind it. The SDK remembers the password and\nsends it automatically when you download — you don't pass it again:\n\n```ts\nconst result = await client.convert('statement.docx', 'pdf', null, { downloadPassword: 'hunter2' });\nawait result.save('statement.pdf'); // the password is applied for you\n```\n\nThe download URL still needs the password from anywhere else (a browser, cURL, another process), via\nthe `X-Api2convert-Download-Password` header. When you already hold an `OutputFile` — e.g. from the Jobs API —\nhand the password to `download()`:\n\n```ts\nawait client.download(output, 'hunter2').save('out/');\n```\n\n## Asynchronous conversions & webhooks\n\nFor long-running jobs, start the conversion and get notified via a webhook instead of waiting:\n\n```ts\nconst job = await client.convertAsync('movie.mov', 'mp4', null, {\n  callback: 'https://your-app.example.com/webhooks/api2convert',\n});\n```\n\nIn your webhook handler, verify and parse the callback:\n\n```ts\nimport { Api2Convert, SignatureVerificationError } from '@api2convert/sdk';\n\nconst payload = rawBody; // the RAW request body (string or Buffer)\nconst signature = req.headers['x-oc-signature'];\n\ntry {\n  const event = Api2Convert.webhooks().constructEvent(payload, signature, 'YOUR_WEBHOOK_SECRET');\n  const job = event.job;\n  // ... react to job.status.code ...\n} catch (err) {\n  if (err instanceof SignatureVerificationError) {\n    // respond 400\n  }\n}\n```\n\n> Signed webhooks are being rolled out. Until they are enabled for your account no signature is sent\n> — call `Api2Convert.webhooks().parse(payload)` (or pass an empty secret) to deserialize the\n> callback without verifying.\n\n## Cloud storage\n\nRead an input straight from your own S3/Azure/FTP/Google Cloud storage, and/or deliver the converted\noutput into a bucket — no need to route bytes through your app. Credentials ride in the request body,\nso the SDK masks the whole credentials object to `[REDACTED]` on inspection/logging and never puts it\nin an error message.\n\nRead the input from Amazon S3 and save the result locally (per-provider factory; flat, lowercase keys):\n\n```ts\nimport { Api2Convert, CloudInput } from '@api2convert/sdk';\n\nconst input = CloudInput.amazonS3('my-bucket', 'invoices/march.docx', 'AKIA…', 'wJalr…');\nconst result = await client.convert(input, 'pdf');\nawait result.save('march.pdf');\n```\n\nDeliver the output into a bucket via an `OutputTarget` and the `outputTargets` option — when an output\ntarget is set the conversion delivers straight to your storage and there's **no** local download, so\n`convert()` returns the completed job:\n\n```ts\nimport { OutputTarget, CloudProvider } from '@api2convert/sdk';\n\nconst target = OutputTarget.of(\n  CloudProvider.AmazonS3,\n  { bucket: 'my-bucket', file: 'out/report.pdf' },\n  { accesskeyid: 'AKIA…', secretaccesskey: 'wJalr…' },\n);\nawait client.convert('report.docx', 'pdf', null, { outputTargets: [target] });\n```\n\n`azure`, `ftp` and `googleCloud` have matching `CloudInput` input factories; output uses the generic\n`OutputTarget` for every provider.\n\n## Error handling\n\nEvery failure is an exception extending `Api2ConvertError`:\n\n```ts\nimport {\n  AuthenticationError,\n  ConversionFailedError,\n  RateLimitError,\n  ValidationError,\n} from '@api2convert/sdk';\n\ntry {\n  await (await client.convert('photo.png', 'jpg')).save('photo.jpg');\n} catch (err) {\n  if (err instanceof ValidationError) {\n    // bad target / option — err.message explains\n  } else if (err instanceof AuthenticationError) {\n    // bad or missing API key\n  } else if (err instanceof RateLimitError) {\n    // too many requests — retry after err.retryAfter seconds\n  } else if (err instanceof ConversionFailedError) {\n    // the job failed — inspect err.errors()\n  }\n}\n```\n\n| Error                        | When                                                     |\n| ---------------------------- | -------------------------------------------------------- |\n| `AuthenticationError`        | 401 / 403 — bad or missing key                           |\n| `PaymentRequiredError`       | 402 — no remaining quota                                 |\n| `ValidationError`            | 400 / 422 — invalid request (e.g. unknown target)        |\n| `NotFoundError`              | 404 — resource doesn't exist                             |\n| `RateLimitError`             | 429 — exposes `retryAfter`                               |\n| `ServerError`                | 5xx                                                      |\n| `ConversionFailedError`      | the job reached `failed`; exposes `.job` and `.errors()` |\n| `ConversionTimeoutError`     | the job didn't finish within the poll timeout            |\n| `NetworkError`               | a transport failure / non-JSON response / malformed URL  |\n| `SignatureVerificationError` | a webhook payload failed verification                    |\n\nTransient failures (429, 5xx, network errors) are **retried automatically** with jittered exponential\nbackoff. A non-idempotent `POST` (e.g. creating a job) is never blindly retried, so a transient error\ncan't create a duplicate job — pass an idempotency key to make it retry-safe:\n`client.jobs().create(payload, 'my-idempotency-key')`.\n\n## Power user: the full job API\n\n`convert()` is sugar over the Jobs API. Drop down to it for compound jobs, merges, presets, custom\npolling or job chaining:\n\n```ts\nconst job = await client.jobs().create({\n  process: false,\n  conversion: [{ target: 'pdf', options: { pdf_a: true } }],\n});\n\nawait client.jobs().upload(job, 'contract.docx'); // local file\nawait client.jobs().addInput(job.id, {\n  type: 'remote',\n  source: 'https://example.com/appendix.docx',\n});\n\nawait client.jobs().start(job.id);\nconst done = await client.jobs().wait(job.id, 120); // poll to completion (120s timeout)\n\nfor (const output of done.output) {\n  await client.download(output).save('out/');\n}\n```\n\nAvailable resources: `jobs()`, `conversions()` (the catalog + option discovery), `presets()`,\n`stats()`, `contracts()`.\n\nDiscover the valid options for any target:\n\n```ts\nconst options = await client.options('jpg'); // -> { quality: {...}, width: {...}, ... }\n```\n\n## Configuration\n\n```ts\nconst client = new Api2Convert('YOUR_API_KEY', {\n  timeout: 30, // per-request network timeout (seconds)\n  maxRetries: 2, // automatic retries for transient failures\n  pollInterval: 1.0, // first poll interval when waiting (seconds)\n  pollMaxInterval: 5.0, // backoff cap (seconds)\n  pollTimeout: 300, // give up waiting after this many seconds\n});\n```\n\nBring your own HTTP transport by implementing `HttpSender` and passing it as `httpSender`, or supply\na custom `fetch` via `new FetchHttpSender(myFetch)`.\n\n## Security — never publish your API key\n\n- **Never hard-code or commit your API key.** Load it from the environment (`API2CONVERT_API_KEY`) or\n  a secrets manager.\n- In CI, store it as a **masked & protected** secret and never print it to logs.\n- Treat the per-job upload **token** and your **webhook signing secret** with the same care.\n- The SDK never logs your key/token and never puts them in exception messages. A request carrying any\n  secret header never follows a redirect (a redirect could otherwise forward the secret to another\n  host); only the self-contained, no-secret download path follows redirects.\n- If a key is ever exposed, **revoke and rotate it** in the API2Convert dashboard immediately.\n\nSee [`SECURITY.md`](SECURITY.md).\n\n## Development\n\n```bash\nnpm run check          # lint + typecheck + unit tests + security suite + audit\nnpm test               # offline unit tests only\nnpm run test:security  # the independent security suite (real loopback servers)\nnpm run build          # emit dual ESM + CJS + type declarations to dist/\n```\n\nLive conformance tests run against the real API when `API2CONVERT_API_KEY` is set (they auto-skip\notherwise):\n\n```bash\nAPI2CONVERT_API_KEY=... npm run test:live\n```\n\nThe [live conformance suite](test/live/conformance.test.ts) doubles as an executable, end-to-end\ntour of the SDK: it runs each documented example against the real API and asserts success, plus two\nnegative scenarios (an unknown target is a typed validation error; a bad key is a typed\nauthentication error that never leaks the key). It runs automatically against the real API on every\nrelease tag (see `.github/workflows/live-conformance.yml`), so a published version is always\nverified end to end.\n\nEvery guide has a matching runnable program in [`examples/`](examples/). Run one with a real key:\n\n```bash\nAPI2CONVERT_API_KEY=... npx tsx examples/quickstart.ts\n```\n\n| Example                                                 | What it shows                                                    |\n| ------------------------------------------------------- | ---------------------------------------------------------------- |\n| [`quickstart.ts`](examples/quickstart.ts)               | Convert a remote JPG to PNG, fetch the job, download the output. |\n| [`convert-files.ts`](examples/convert-files.ts)         | Browse the conversions catalog, then convert.                    |\n| [`uploading-files.ts`](examples/uploading-files.ts)     | Upload a local file and convert it in one call.                  |\n| [`job-lifecycle.ts`](examples/job-lifecycle.ts)         | Drive create → add input → start → wait → outputs by hand.       |\n| [`add-watermark.ts`](examples/add-watermark.ts)         | Stamp a PNG onto a PDF (a two-input job).                        |\n| [`create-thumbnails.ts`](examples/create-thumbnails.ts) | Render the first PDF page to a PNG thumbnail.                    |\n| [`compress-files.ts`](examples/compress-files.ts)       | Compress a JPG with the compress operation.                      |\n| [`create-archives.ts`](examples/create-archives.ts)     | Bundle a PDF and a PNG into a ZIP.                               |\n| [`create-hashes.ts`](examples/create-hashes.ts)         | Compute the SHA-256 of a file.                                   |\n| [`extract-assets.ts`](examples/extract-assets.ts)       | Extract embedded assets from a DOCX.                             |\n| [`file-analysis.ts`](examples/file-analysis.ts)         | Read a file's metadata as JSON.                                  |\n| [`compare-files.ts`](examples/compare-files.ts)         | Diff two images with SSIM.                                       |\n| [`capture-website.ts`](examples/capture-website.ts)     | Screenshot a URL to PNG.                                         |\n| [`audio-operations.ts`](examples/audio-operations.ts)   | Transcode a WAV to AAC with explicit codec settings.             |\n| [`image-operations.ts`](examples/image-operations.ts)   | Resize an image, cropping to keep aspect ratio.                  |\n| [`webhooks.ts`](examples/webhooks.ts)                   | Start an async job with a callback URL and verify the callback.  |\n| [`presets.ts`](examples/presets.ts)                     | List saved conversion presets.                                   |\n| [`statistics.ts`](examples/statistics.ts)               | Read API usage for a month.                                      |\n| [`rate-limits.ts`](examples/rate-limits.ts)             | Read the account's contract/quota information.                   |\n| [`authentication.ts`](examples/authentication.ts)       | Verify your API key by listing your jobs.                        |\n\nThis SDK is hand-written and kept in sync with the API by an AI agent — see [`AGENTS.md`](AGENTS.md)\nand [`docs/SDK_CONTRACT.md`](docs/SDK_CONTRACT.md). Notable changes are recorded in\n[`docs/CHANGELOG.md`](docs/CHANGELOG.md).\n\n## License\n\nMIT — see [`LICENSE`](LICENSE).\n","readmeFilename":"README.md"}