{"_id":"@apertur/sdk","_rev":"5-3826da2fad3bc7a6a7a0a0163fbc7844","name":"@apertur/sdk","dist-tags":{"latest":"0.1.8"},"versions":{"0.1.0":{"name":"@apertur/sdk","version":"0.1.0","keywords":["apertur","sdk","upload","image","api"],"license":"MIT","_id":"@apertur/sdk@0.1.0","maintainers":[{"name":"apertur-dev-account","email":"npmjsaccount@apertur.ca"}],"homepage":"https://github.com/apertur/apertur#readme","bugs":{"url":"https://github.com/apertur/apertur/issues"},"dist":{"shasum":"accaee2d09739536e80e612f3e3a24a5c873fbbf","tarball":"https://registry.npmjs.org/@apertur/sdk/-/sdk-0.1.0.tgz","fileCount":38,"integrity":"sha512-pOPu9dHzYoNZIaGelndAiB9jC+5LnlYxC4SHlKAM1Ad7c+NgDVFBDOH3ai8XlpimNLDn9iw7BBjpCDsXcSvoOQ==","signatures":[{"sig":"MEUCIQDqvcEzh0eyGMLoxuaSxTm+TpSAFE0aZn648tFrl5EmEAIgGWc4R/AjrlFnbvRRXwGrxu/fkUCz7yHewXceYYvNadU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52378},"main":"dist/index.js","_from":"file:apertur-sdk-0.1.0.tgz","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run","build":"tsc","test:watch":"vitest"},"_npmUser":{"name":"apertur-dev-account","email":"npmjsaccount@apertur.ca"},"_resolved":"/tmp/2f4420b6fcdb60aa52c2cb2eb8caa005/apertur-sdk-0.1.0.tgz","_integrity":"sha512-pOPu9dHzYoNZIaGelndAiB9jC+5LnlYxC4SHlKAM1Ad7c+NgDVFBDOH3ai8XlpimNLDn9iw7BBjpCDsXcSvoOQ==","repository":{"url":"git+https://github.com/apertur/apertur.git","type":"git","directory":"packages/client-node"},"_npmVersion":"10.8.2","description":"Official Apertur SDK for Node.js","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"msw":"^2.12.14","vitest":"^1.0.0","typescript":"^5.0.0","@types/node":"^25.5.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.0_1775854564276_0.9425463251184689","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@apertur/sdk","version":"0.1.1","keywords":["apertur","sdk","upload","image","api"],"license":"MIT","_id":"@apertur/sdk@0.1.1","maintainers":[{"name":"apertur-dev-account","email":"npmjsaccount@apertur.ca"}],"homepage":"https://github.com/apertur-dev/apertur-node#readme","bugs":{"url":"https://github.com/apertur-dev/apertur-node/issues"},"dist":{"shasum":"cd8444ecb0aad5d79ff9874636465dfbc559117b","tarball":"https://registry.npmjs.org/@apertur/sdk/-/sdk-0.1.1.tgz","fileCount":38,"integrity":"sha512-g6iEWVKK+CIKiIUPKXSjcSYB/HRmb2GeQZb+5qi3jhoi8JE+RacFYeuiRi/Odtt4o9G0XrDUm2NoFK4io813BQ==","signatures":[{"sig":"MEUCIDVZelm9QJiPqnKTCNFq6/PhY8qU+FXpnt5kGKyCK/aCAiEAvAZ+16erxqSdtQz1tZSaBGYQg5wjKYYrYPt3KuyJS24=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52387},"main":"dist/index.js","_from":"file:apertur-sdk-0.1.1.tgz","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run","build":"tsc","test:watch":"vitest"},"_npmUser":{"name":"apertur-dev-account","email":"npmjsaccount@apertur.ca"},"_resolved":"/tmp/33ca93bd1e273ece716d8d06b8a64b09/apertur-sdk-0.1.1.tgz","_integrity":"sha512-g6iEWVKK+CIKiIUPKXSjcSYB/HRmb2GeQZb+5qi3jhoi8JE+RacFYeuiRi/Odtt4o9G0XrDUm2NoFK4io813BQ==","repository":{"url":"git+https://github.com/apertur-dev/apertur-node.git","type":"git","directory":"packages/client-node"},"_npmVersion":"10.8.2","description":"Official Apertur SDK for Node.js","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"msw":"^2.12.14","vitest":"^1.0.0","typescript":"^5.0.0","@types/node":"^25.5.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.1_1775861489372_0.32503472494176733","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@apertur/sdk","version":"0.1.2","keywords":["apertur","sdk","upload","image","api"],"license":"MIT","_id":"@apertur/sdk@0.1.2","maintainers":[{"name":"apertur-dev-account","email":"npmjsaccount@apertur.ca"}],"homepage":"https://github.com/Apertur-dev/apertur-node#readme","bugs":{"url":"https://github.com/Apertur-dev/apertur-node/issues"},"dist":{"shasum":"24bed37b9a77f4cf11dbabcb955e5f300130e65c","tarball":"https://registry.npmjs.org/@apertur/sdk/-/sdk-0.1.2.tgz","fileCount":38,"integrity":"sha512-H5SL6UCJiwZwvIV1w6c1Z0y7hF2V+KcgqD05OU8x8Poo+rGRC3XRYJD9d6g0ROufFV5QpaCBgXtaKnvtdrn1aw==","signatures":[{"sig":"MEUCIQDgkLB3fqTFg5G8U0UlS9N0xZYKuZZnDKBPL80avhYDhwIgPv+Qe/ePQVsTQuYbR1ERPILBPOW5QDvyVZEzjq6zpW8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52387},"main":"dist/index.js","_from":"file:apertur-sdk-0.1.2.tgz","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run","build":"tsc","test:watch":"vitest"},"_npmUser":{"name":"apertur-dev-account","email":"npmjsaccount@apertur.ca"},"_resolved":"/tmp/4574ff61c858518c29eab292f5c2eac3/apertur-sdk-0.1.2.tgz","_integrity":"sha512-H5SL6UCJiwZwvIV1w6c1Z0y7hF2V+KcgqD05OU8x8Poo+rGRC3XRYJD9d6g0ROufFV5QpaCBgXtaKnvtdrn1aw==","repository":{"url":"git+https://github.com/Apertur-dev/apertur-node.git","type":"git","directory":"packages/client-node"},"_npmVersion":"10.8.2","description":"Official Apertur SDK for Node.js","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"msw":"^2.12.14","vitest":"^1.0.0","typescript":"^5.0.0","@types/node":"^25.5.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.2_1775861565480_0.8299799368554732","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@apertur/sdk","version":"0.1.5","keywords":["apertur","sdk","upload","image","api"],"license":"MIT","_id":"@apertur/sdk@0.1.5","maintainers":[{"name":"apertur-dev-account","email":"npmjsaccount@apertur.ca"}],"homepage":"https://github.com/Apertur-dev/apertur-node#readme","bugs":{"url":"https://github.com/Apertur-dev/apertur-node/issues"},"dist":{"shasum":"595f382f9f2165d9f3e1354bfdee165c9e8bea94","tarball":"https://registry.npmjs.org/@apertur/sdk/-/sdk-0.1.5.tgz","fileCount":38,"integrity":"sha512-vHDBJ2sOeVNoDZlsb1N50msxK8EfI04W1DU1SdX7wjtnUT5AExd3f2KY6xNcCW4iXdQbKy1ch0Dx+4B4M208wQ==","signatures":[{"sig":"MEYCIQCQMgJbx7o2nGwxjakwWSRSWOh0oUQiH/NWRJZlbecHPgIhAJbRdorYeQtEmtANK6FiOL4wKfTUlyJtWwDwjk0418SI","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":53336},"main":"dist/index.js","_from":"file:apertur-sdk-0.1.5.tgz","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run","build":"tsc","test:watch":"vitest"},"_npmUser":{"name":"apertur-dev-account","email":"npmjsaccount@apertur.ca"},"_resolved":"/tmp/c4ea6eef741807f2efb33f5ea534009d/apertur-sdk-0.1.5.tgz","_integrity":"sha512-vHDBJ2sOeVNoDZlsb1N50msxK8EfI04W1DU1SdX7wjtnUT5AExd3f2KY6xNcCW4iXdQbKy1ch0Dx+4B4M208wQ==","repository":{"url":"git+https://github.com/Apertur-dev/apertur-node.git","type":"git","directory":"packages/client-node"},"_npmVersion":"11.6.2","description":"Official Apertur SDK for Node.js","directories":{},"_nodeVersion":"24.11.1","_hasShrinkwrap":false,"devDependencies":{"msw":"^2.12.14","vitest":"^1.0.0","typescript":"^5.0.0","@types/node":"^25.5.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.5_1776534817739_0.015736949162682867","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@apertur/sdk","version":"0.1.8","description":"Official Apertur SDK for Node.js","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"build":"tsc","test":"vitest run","test:watch":"vitest"},"engines":{"node":">=18"},"license":"MIT","dependencies":{"socket.io-client":"^4.8.3"},"repository":{"type":"git","url":"git+https://github.com/Apertur-dev/apertur-node.git","directory":"packages/client-node"},"keywords":["apertur","sdk","upload","image","api"],"devDependencies":{"@types/node":"^25.5.0","msw":"^2.12.14","typescript":"^5.0.0","vitest":"^1.0.0"},"gitHead":"4dad8db443e75ede061843cf593497d07d3a39fb","_id":"@apertur/sdk@0.1.8","bugs":{"url":"https://github.com/Apertur-dev/apertur-node/issues"},"homepage":"https://github.com/Apertur-dev/apertur-node#readme","_nodeVersion":"24.11.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-v+PG2g2exRigV5wSs42/11vxc6wlTxUet9GYYG1qeRsu43XoiOP2mk0ewCvqXtGMrAGxXaK9mgykkGPZuQyt4A==","shasum":"a92a0bfe7ba045d860271c0538b93b3b174002ea","tarball":"https://registry.npmjs.org/@apertur/sdk/-/sdk-0.1.8.tgz","fileCount":38,"unpackedSize":59973,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCQTV3Rpes04KWy1yCo0Lq3c8gbQyDaRthabpLk2S3M6AIgHufyydEbGD1NUwZAFhQyTNJ/8fVdRr96sl6Jl5Ds4GA="}]},"_npmUser":{"name":"apertur-dev-account","email":"npmjsaccount@apertur.ca"},"directories":{},"maintainers":[{"name":"apertur-dev-account","email":"npmjsaccount@apertur.ca"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_0.1.8_1785782823577_0.4370054490319615"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-10T20:56:04.184Z","modified":"2026-08-03T18:47:03.923Z","0.1.0":"2026-04-10T20:56:04.435Z","0.1.1":"2026-04-10T22:51:29.508Z","0.1.2":"2026-04-10T22:52:45.614Z","0.1.5":"2026-04-18T17:53:37.887Z","0.1.8":"2026-08-03T18:47:03.724Z"},"bugs":{"url":"https://github.com/Apertur-dev/apertur-node/issues"},"license":"MIT","homepage":"https://github.com/Apertur-dev/apertur-node#readme","keywords":["apertur","sdk","upload","image","api"],"repository":{"type":"git","url":"git+https://github.com/Apertur-dev/apertur-node.git","directory":"packages/client-node"},"description":"Official Apertur SDK for Node.js","maintainers":[{"name":"apertur-dev-account","email":"npmjsaccount@apertur.ca"}],"readme":"# @apertur/sdk\n\nOfficial Node.js SDK for the [Apertur](https://apertur.ca) API. Collect photos from any mobile device via QR codes — no app required.\n\n## Installation\n\n```bash\nnpm install @apertur/sdk\n```\n\n## Quick Start\n\nGet up and running with a single session and image upload in just a few lines.\n\n```javascript\nconst { Apertur } = require('@apertur/sdk');\n// or: import { Apertur } from '@apertur/sdk';\n\nconst client = new Apertur({ apiKey: 'aptr_xxxx' });\n\n// Create a session and upload an image\nconst session = await client.sessions.create({ tags: ['demo'] });\nconst result = await client.upload.image(session.id, './photo.jpg');\nconsole.log(`Uploaded: ${result.filename} (${result.size_bytes} bytes)`);\n```\n\n## Authentication\n\nTwo auth methods: API key (for server-to-server) and OAuth token (for third-party integrations).\n\n```javascript\n// API Key\nconst client = new Apertur({ apiKey: 'aptr_your_key_here' });\n\n// OAuth Token\nconst client = new Apertur({ oauthToken: 'aptr_oauth_your_token' });\n\n// Custom base URL (for self-hosted or staging)\nconst client = new Apertur({ apiKey: 'aptr_xxx', baseUrl: 'https://api.aptr.ca' });\n```\n\nSee [Authentication documentation](https://docs.apertur.ca/authentication)\n\n## Sessions\n\nCreate upload sessions, check status, and manage password-protected sessions.\n\n```javascript\n// Create a session\nconst session = await client.sessions.create({\n  tags: ['event-photos'],\n  expires_in_hours: 48,\n  max_images: 50,\n  password: 'secret123',\n  long_polling: true,\n});\n\n// Get session info\nconst info = await client.sessions.get(session.id);\n\n// Verify password for protected sessions\nconst { valid } = await client.sessions.verifyPassword(session.id, 'secret123');\n\n// Check delivery status\nconst status = await client.sessions.deliveryStatus(session.id);\n```\n\nSee [Sessions documentation](https://docs.apertur.ca/upload-sessions)\n\n## Uploading Images\n\nUpload images as Buffer, file path, or ReadStream. Supports optional server-side encryption.\n\n```javascript\n// Upload from file path\nawait client.upload.image(sessionId, './photo.jpg', {\n  filename: 'vacation.jpg',\n  mimeType: 'image/jpeg',\n  source: 'gallery',\n});\n\n// Upload from Buffer\nconst buffer = fs.readFileSync('./photo.png');\nawait client.upload.image(sessionId, buffer, { mimeType: 'image/png' });\n\n// Upload with server-side encryption\nconst { publicKey } = await client.encryption.getServerKey();\nawait client.upload.imageEncrypted(sessionId, './photo.jpg', publicKey);\n```\n\nSee [Upload documentation](https://docs.apertur.ca/upload-sessions)\n\n## Long Polling\n\nRetrieve uploaded images via polling instead of webhooks. Requires session created with `long_polling: true`.\n\n```javascript\n// Manual poll cycle\nconst { images } = await client.polling.list(sessionId);\nfor (const image of images) {\n  const buffer = await client.polling.download(sessionId, image.id);\n  fs.writeFileSync(`./downloads/${image.filename}`, buffer);\n  await client.polling.ack(sessionId, image.id);\n}\n\n// Automatic poll + process loop\nconst controller = new AbortController();\n\nawait client.polling.pollAndProcess(sessionId, async (image, data) => {\n  console.log(`Received: ${image.filename} (${image.size_bytes} bytes)`);\n  fs.writeFileSync(`./output/${image.filename}`, data);\n}, { interval: 3000, signal: controller.signal });\n\n// Stop polling\ncontroller.abort();\n```\n\nSee [Long Polling documentation](https://docs.apertur.ca/long-polling)\n\n## Receiving Webhooks\n\nVerify webhook signatures to ensure payloads are authentic. Three verification methods match the Apertur signature schemes.\n\n```javascript\nimport { verifyWebhookSignature, verifyEventSignature, verifySvixSignature } from '@apertur/sdk';\n\n// Express middleware for image delivery webhooks\napp.post('/webhook', express.raw({ type: '*/*' }), (req, res) => {\n  const signature = req.headers['x-apertur-signature'];\n  const isValid = verifyWebhookSignature(req.body, signature, WEBHOOK_SECRET);\n  if (!isValid) return res.status(401).send('Invalid signature');\n  // Process the image...\n  res.status(200).send('OK');\n});\n\n// Event webhook (HMAC SHA256)\nconst isValid = verifyEventSignature(\n  body,\n  req.headers['x-apertur-timestamp'],\n  req.headers['x-apertur-signature'],\n  EVENT_WEBHOOK_SECRET\n);\n\n// Event webhook (Svix)\nconst isValid = verifySvixSignature(\n  body,\n  req.headers['svix-id'],\n  req.headers['svix-timestamp'],\n  req.headers['svix-signature'],\n  EVENT_WEBHOOK_SECRET\n);\n```\n\nSee [Webhook documentation](https://docs.apertur.ca/webhooks)\n\n## Destinations\n\nManage delivery destinations (webhook, S3, Google Drive, etc.).\n\n```javascript\nconst destinations = await client.destinations.list(projectId);\n\nconst webhook = await client.destinations.create(projectId, {\n  type: 'webhook',\n  name: 'My Backend',\n  config: { url: 'https://api.example.com/photos', format: 'json_base64' },\n});\n\nawait client.destinations.test(projectId, webhook.id);\nawait client.destinations.update(projectId, webhook.id, { isActive: false });\nawait client.destinations.delete(projectId, webhook.id);\n```\n\nSee [Destinations documentation](https://docs.apertur.ca/destinations)\n\n## API Keys\n\nManage API keys and their default destinations.\n\n```javascript\nconst keys = await client.keys.list(projectId);\n\nconst { key, plainTextKey } = await client.keys.create(projectId, {\n  label: 'Production',\n  maxImages: 100,\n});\nconsole.log(`Save this key: ${plainTextKey}`); // Only shown once!\n\n// Set default destinations for a key\nawait client.keys.setDestinations(key.id, [dest1.id, dest2.id], true); // true = enable long polling\n```\n\nSee [API Keys documentation](https://docs.apertur.ca/api-keys)\n\n## Event Webhooks\n\nSubscribe to project events (uploads, deliveries, billing changes, etc.).\n\n```javascript\nconst webhook = await client.webhooks.create(projectId, {\n  url: 'https://api.example.com/events',\n  topics: ['project.upload.*', 'project.billing.plan_changed'],\n});\n\n// List deliveries\nconst { deliveries } = await client.webhooks.deliveries(projectId, webhook.id);\n\n// Retry a failed delivery\nawait client.webhooks.retryDelivery(projectId, webhook.id, deliveries[0].id);\n```\n\nSee [Event Webhooks documentation](https://docs.apertur.ca/event-webhooks)\n\n## Realtime Events\n\nSubscribe to real-time upload events over Socket.IO. `subscribe()` opens a\nSocket.IO connection, joins the session room (the session UUID is the access\ntoken — no API key is sent on the socket), and returns an event emitter. Call\n`.close()` on it to disconnect.\n\n```javascript\nconst events = client.events.subscribe(sessionId);\n\nevents.on('connected', (data) => console.log('Joined session:', data.sessionId));\nevents.on('image:ready', (data) => console.log('Image ready:', data));\nevents.on('image:delivering', (data) => console.log('Delivering:', data));\nevents.on('image:delivered', (data) => console.log('Delivered to:', data.destinationId));\nevents.on('image:failed', (data) => console.error('Delivery failed:', data));\nevents.on('error', (err) => console.error('Socket error:', err));\n\n// events.close();\n```\n\nSee [Events documentation](https://docs.apertur.ca/realtime-events)\n\n## Error Handling\n\nAll SDK errors extend `AperturError` with typed subclasses for common HTTP failure cases.\n\n```javascript\nimport { AperturError, RateLimitError, NotFoundError, AuthenticationError } from '@apertur/sdk';\n\ntry {\n  await client.sessions.create();\n} catch (err) {\n  if (err instanceof RateLimitError) {\n    console.log(`Rate limited. Retry after: ${err.retryAfter}s`);\n  } else if (err instanceof AuthenticationError) {\n    console.log('Invalid API key');\n  } else if (err instanceof NotFoundError) {\n    console.log('Resource not found');\n  } else if (err instanceof AperturError) {\n    console.log(`API error ${err.statusCode}: ${err.message} (code: ${err.code})`);\n  }\n}\n```\n\n## API Reference\n\nFor complete API documentation, visit [docs.apertur.ca](https://docs.apertur.ca).\n\n## License\n\nMIT\n","readmeFilename":"README.md"}