{"_id":"@alisamadiillc/agency-api","_rev":"6-97524ef0734b2ecd3db39cef3f794aef","name":"@alisamadiillc/agency-api","dist-tags":{"latest":"0.3.5"},"versions":{"0.1.0":{"name":"@alisamadiillc/agency-api","version":"0.1.0","keywords":["agency-api","email","uploads","r2","api-client"],"license":"MIT","_id":"@alisamadiillc/agency-api@0.1.0","maintainers":[{"name":"alisamadii","email":"a@alisamadii.com"}],"homepage":"https://github.com/alisamadiii/agency-api#readme","bugs":{"url":"https://github.com/alisamadiii/agency-api/issues"},"dist":{"shasum":"0cb9b06bc14e4746ec0f99d31d15cbdace61ff31","tarball":"https://registry.npmjs.org/@alisamadiillc/agency-api/-/agency-api-0.1.0.tgz","fileCount":6,"integrity":"sha512-aPLaWeFyttM6opAVr24qR3j1CvQAsvcltxHQywqnhhn9CXmbkfIoUXondoIaHpKXcgw0n1Gc6TnECgmoC7Ifng==","signatures":[{"sig":"MEUCIBVblJilt/hdDKal/X/wzVpS75SYlvcceR3w8A1a8WB+AiEA7hXImQlkcz0QayPR+h1psW2D7LFyPgYms8PHyzSRp6E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28104},"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"}}},"gitHead":"337dec25dc8545ae55d3e15b226053432e995b85","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit","prepublishOnly":"pnpm run typecheck && pnpm run build"},"_npmUser":{"name":"alisamadii","email":"a@alisamadii.com"},"repository":{"url":"git+https://github.com/alisamadiii/agency-api.git","type":"git","directory":"packages/api-client"},"_npmVersion":"10.9.3","description":"TypeScript client for the agency API — emails and uploads.","directories":{},"sideEffects":false,"_nodeVersion":"22.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","typescript":"^5.7.2"},"_npmOperationalInternal":{"tmp":"tmp/agency-api_0.1.0_1783795890109_0.6611061502608437","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@alisamadiillc/agency-api","version":"0.1.1","keywords":["agency-api","email","uploads","r2","api-client"],"license":"MIT","_id":"@alisamadiillc/agency-api@0.1.1","maintainers":[{"name":"alisamadii","email":"a@alisamadii.com"}],"homepage":"https://github.com/alisamadiii/agency-api#readme","bugs":{"url":"https://github.com/alisamadiii/agency-api/issues"},"dist":{"shasum":"d4f9f4c2e62d54baf5257dcab36ebb155ccb02e2","tarball":"https://registry.npmjs.org/@alisamadiillc/agency-api/-/agency-api-0.1.1.tgz","fileCount":6,"integrity":"sha512-F6PkYl3Pue0ZWlh/IgAkyqWmxC7SrfmQEmuAW5hnhrKYlZCAouq6jt6OMEo70neC8BMy7LbMEmezDODHaV+2qw==","signatures":[{"sig":"MEYCIQDXD61osnPXLpUiSfLRFWduvotI7HRASza0Ao6PryBBbAIhALGlWUxFXV27MZRgMKXwXbNHXDxl9+r78LpWNZFWBkRo","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29925},"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"}}},"gitHead":"f3f0bb3162377b648f0ff7f901a966f59ad25306","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit","prepublishOnly":"pnpm run typecheck && pnpm run build"},"_npmUser":{"name":"alisamadii","email":"a@alisamadii.com"},"repository":{"url":"git+https://github.com/alisamadiii/agency-api.git","type":"git","directory":"packages/api-client"},"_npmVersion":"10.9.3","description":"TypeScript client for the agency API — emails and uploads.","directories":{},"sideEffects":false,"_nodeVersion":"22.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","typescript":"^5.7.2"},"_npmOperationalInternal":{"tmp":"tmp/agency-api_0.1.1_1783796640124_0.1605341611409301","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@alisamadiillc/agency-api","version":"0.1.3","keywords":["agency-api","email","uploads","r2","api-client"],"license":"MIT","_id":"@alisamadiillc/agency-api@0.1.3","maintainers":[{"name":"alisamadii","email":"a@alisamadii.com"}],"homepage":"https://github.com/alisamadiii/agency-api#readme","bugs":{"url":"https://github.com/alisamadiii/agency-api/issues"},"dist":{"shasum":"d90ea8107ea55aaa8a6c5564a02697fd2a5d709d","tarball":"https://registry.npmjs.org/@alisamadiillc/agency-api/-/agency-api-0.1.3.tgz","fileCount":6,"integrity":"sha512-hC0QHco8+bB0M8KVmiW+9E0ImEA8DnQmEqAy2b+aGqjaP5h/u5+0bHOl+S4dQFZQbJpvWWMgXFXlI0NkpY7Yiw==","signatures":[{"sig":"MEUCIQCVCOCoeVuS+FiFqBpEWYWAtzmHgWjNqSWo4yRoq26S2AIgP1o0+VzxpBwAgOuDwjaTHTnisZ5kJCjmVlD58ZVRiuw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":33708},"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"}}},"gitHead":"8e139b7afc0969b6a05e4a5f62fe105eeeb751b9","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit","prepublishOnly":"pnpm run typecheck && pnpm run build"},"_npmUser":{"name":"alisamadii","email":"a@alisamadii.com"},"repository":{"url":"git+https://github.com/alisamadiii/agency-api.git","type":"git","directory":"packages/api-client"},"_npmVersion":"10.9.3","description":"TypeScript client for the agency API — emails and uploads.","directories":{},"sideEffects":false,"_nodeVersion":"22.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","typescript":"^5.7.2"},"_npmOperationalInternal":{"tmp":"tmp/agency-api_0.1.3_1783995024373_0.9058135726273593","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@alisamadiillc/agency-api","version":"0.2.1","keywords":["agency-api","email","uploads","r2","api-client"],"license":"MIT","_id":"@alisamadiillc/agency-api@0.2.1","maintainers":[{"name":"alisamadii","email":"a@alisamadii.com"}],"homepage":"https://github.com/alisamadiii/Portfolio#readme","bugs":{"url":"https://github.com/alisamadiii/Portfolio/issues"},"dist":{"shasum":"b5589d1b50cc04dda01c945dfbbaaf69c22c1e12","tarball":"https://registry.npmjs.org/@alisamadiillc/agency-api/-/agency-api-0.2.1.tgz","fileCount":6,"integrity":"sha512-Q0Ikh/9qRFf9v+NRdlVCCdIB0lZ7J0a3b2+b4YP1ib9mJbeUs04qdYpTqB5XpuoK9dj/MfahZm1gLpS1jzU0IA==","signatures":[{"sig":"MEYCIQCeh/ej7cx6RH6gcREehhCIOsV6YMt8QBLA8lQ0ItcZlQIhAKZouvu2OftLJXQJXGCSsqb3nKE/AXi5KZIAvc7jyIZ8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":75402},"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"}}},"gitHead":"0bcc97cd1f8c5611ddc4b2806b4b77c008a61277","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","prepare":"pnpm run build","typecheck":"tsc --noEmit","prepublishOnly":"pnpm run typecheck && pnpm run build"},"_npmUser":{"name":"alisamadii","email":"a@alisamadii.com"},"repository":{"url":"git+https://github.com/alisamadiii/Portfolio.git","type":"git","directory":"packages/api-client"},"_npmVersion":"10.9.3","description":"TypeScript client for the agency API — emails and uploads.","directories":{},"sideEffects":false,"_nodeVersion":"22.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/agency-api_0.2.1_1785197695662_0.884513204248565","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@alisamadiillc/agency-api","version":"0.3.0","keywords":["agency-api","email","uploads","r2","api-client"],"license":"MIT","_id":"@alisamadiillc/agency-api@0.3.0","maintainers":[{"name":"alisamadii","email":"a@alisamadii.com"}],"homepage":"https://github.com/alisamadiii/Portfolio#readme","bugs":{"url":"https://github.com/alisamadiii/Portfolio/issues"},"dist":{"shasum":"c2779061ad7d19d09592ce27203d5e70c090362f","tarball":"https://registry.npmjs.org/@alisamadiillc/agency-api/-/agency-api-0.3.0.tgz","fileCount":6,"integrity":"sha512-yucv7TY3iwBMirTaKJ4cGe6MzejJ46JpdRTVNjnD53jVMVdAbYgm1p1r4zQUD32XIv9do3LwHyHwsfQC8TjJIQ==","signatures":[{"sig":"MEUCIHZa92SsCek2881c2+/YyU/tqiWX1GKBE8AGhs263xq8AiEAoYlP4RmHFbIoWTvGd/UO4vzT+IuW5aXp91lbXrCmB/4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":75850},"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"}}},"gitHead":"f48d42dd0ad19cebccb477959c7045f5203c81c0","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","prepare":"pnpm run build","typecheck":"tsc --noEmit","prepublishOnly":"pnpm run typecheck && pnpm run build"},"_npmUser":{"name":"alisamadii","email":"a@alisamadii.com"},"repository":{"url":"git+https://github.com/alisamadiii/Portfolio.git","type":"git","directory":"packages/api-client"},"_npmVersion":"10.9.3","description":"TypeScript client for the agency API — emails and uploads.","directories":{},"sideEffects":false,"_nodeVersion":"22.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/agency-api_0.3.0_1785695238641_0.3963652765518775","host":"s3://npm-registry-packages-npm-production"}},"0.3.5":{"name":"@alisamadiillc/agency-api","version":"0.3.5","description":"TypeScript client for the agency API — emails and uploads.","type":"module","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"}}},"sideEffects":false,"engines":{"node":">=18"},"scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit","prepare":"pnpm run build","prepublishOnly":"pnpm run typecheck && pnpm run build"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/alisamadiii/Portfolio.git","directory":"packages/api-client"},"keywords":["agency-api","email","uploads","r2","api-client"],"devDependencies":{"tsup":"^8.3.5","typescript":"^5.9.3"},"license":"MIT","_id":"@alisamadiillc/agency-api@0.3.5","gitHead":"195b6ba327b7253aa0935ff6d7c4b4fb8b4aa77e","bugs":{"url":"https://github.com/alisamadiii/Portfolio/issues"},"homepage":"https://github.com/alisamadiii/Portfolio#readme","_nodeVersion":"22.19.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-nLU4nkw0/mKY6N4L8VTRSqpmIC6q9GIhS/E4DMNDfOOj7KWdX5XeG3fXTJj14n26O1tuBqbhv6KDGnv0q1TKrw==","shasum":"d9de7248e203620508a89e592f1de9f7721cb7a4","tarball":"https://registry.npmjs.org/@alisamadiillc/agency-api/-/agency-api-0.3.5.tgz","fileCount":6,"unpackedSize":82948,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHO34g8zlXFBq3Fq7FojtFEum8vNTFN0nrAJDlHdc07FAiEAtIUqMfsVfWzZlUbv4I3zObgHhu4Uj7H3GdQ9rsEr0VU="}]},"_npmUser":{"name":"alisamadii","email":"a@alisamadii.com"},"directories":{},"maintainers":[{"name":"alisamadii","email":"a@alisamadii.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/agency-api_0.3.5_1786197092940_0.8270715350290905"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-11T18:51:29.958Z","modified":"2026-08-08T13:51:33.269Z","0.1.0":"2026-07-11T18:51:30.244Z","0.1.1":"2026-07-11T19:04:00.270Z","0.1.3":"2026-07-14T02:10:24.506Z","0.2.1":"2026-07-28T00:14:55.798Z","0.3.0":"2026-08-02T18:27:18.798Z","0.3.5":"2026-08-08T13:51:33.095Z"},"bugs":{"url":"https://github.com/alisamadiii/Portfolio/issues"},"license":"MIT","homepage":"https://github.com/alisamadiii/Portfolio#readme","keywords":["agency-api","email","uploads","r2","api-client"],"repository":{"type":"git","url":"git+https://github.com/alisamadiii/Portfolio.git","directory":"packages/api-client"},"description":"TypeScript client for the agency API — emails and uploads.","maintainers":[{"name":"alisamadii","email":"a@alisamadii.com"}],"readme":"# @alisamadiillc/agency-api\n\nTypeScript client for the agency API — send emails and manage uploads with full type safety. Zero dependencies, works in Node 18+, browsers, and edge runtimes.\n\n## Install\n\n```sh\nnpm install @alisamadiillc/agency-api\n```\n\n## Quickstart\n\nCreate a shared client once:\n\n```ts\n// lib/agency.ts\nimport { AgencyClient } from \"@alisamadiillc/agency-api\";\n\nexport const agency = new AgencyClient(process.env.AGENCY_API_KEY!);\n// custom base URL: new AgencyClient(key, { baseUrl: \"http://localhost:8787\" })\n```\n\nThen import it anywhere:\n\n```ts\nimport { agency } from \"@/lib/agency\";\n\nconst { data, error } = await agency.emails.send({\n  from: \"hello@yourdomain.com\",\n  to: \"user@example.com\", // or [\"a@example.com\", \"b@example.com\"]\n  subject: \"Welcome\",\n  html: \"<p>Hello!</p>\",\n});\n\nif (error) {\n  console.error(error.code, error.message); // e.g. \"RATE_LIMIT_EXCEEDED\"\n} else {\n  console.log(data.id);\n}\n```\n\nEvery method returns `{ data, error }` — it never throws for API or network failures.\n\n## Contact form\n\n`sendContact` is made for public contact forms: the API renders the notification email (name, message, source, device, IP, a reply button) and delivers it to **your account email** — the caller never chooses the recipient, so a browser-exposed key can't be used to spam anyone. The visitor's address becomes the Reply-To.\n\n```ts\nconst { data, error } = await agency.emails.sendContact({\n  name: \"Jane Doe\",\n  email: \"jane@example.com\",\n  message: \"Hi! I'd like to work with you.\",\n  subject: \"Project inquiry\", // optional; defaults to \"New contact from Jane Doe\"\n  source: \"My Site — Contact Form\", // optional; defaults to the page Origin\n  metadata: {\n    // optional; any extra form fields your site collects —\n    Phone: \"+1 555 010 1234\", // rendered as a Details section in the email\n    Company: \"Acme Inc\",\n    Budget: \"$5k–10k\",\n  },\n});\n```\n\nRate limited to **5 requests per 10 minutes per IP** — surface `RATE_LIMIT_EXCEEDED` (429) as a \"please try again in a few minutes\" message.\n\n## Uploads\n\nOne-call upload (presign + PUT handled for you):\n\n```ts\nconst { data, error } = await agency.uploads.upload(file, {\n  path: \"avatars\",\n  naming: \"uuid-filename\", // \"filename\" | \"uuid\" | \"uuid-filename\"\n});\n\nif (data) console.log(data.publicUrl);\n```\n\nOr do the two steps yourself:\n\n```ts\nconst { data: presign } = await agency.uploads.presign({\n  filename: file.name,\n  contentType: file.type,\n  contentLength: file.size,\n});\n\n// Plain fetch — the signature is in the URL. Do NOT add an\n// Authorization header here; it breaks the signature.\nawait fetch(presign!.uploadUrl, {\n  method: \"PUT\",\n  headers: presign!.headers,\n  body: file,\n});\n```\n\nList and delete:\n\n```ts\nconst { data } = await agency.uploads.list({ prefix: \"avatars/\" });\n// data.objects: [{ key, size, lastModified, url }], data.nextCursor for paging\n\nawait agency.uploads.delete({ key: \"avatars/photo.jpg\" });\n```\n\n## Who am I\n\n```ts\nconst { data } = await agency.me.get();\n// data.keyPrefix, data.user.email, data.user.bucketName, ...\n```\n\n## Email history\n\n```ts\nconst { data } = await agency.emails.list({ limit: 20 });\n// data.emails: [{ id, kind, from, to, subject, createdAt, ... }], newest first\n// Next page: pass the last row's createdAt as `before`.\n\nconst { data: html } = await agency.emails.getHtml(data.emails[0].id);\n// html.url — presigned link to the archived HTML, dies in ~60s\n```\n\n## Admin\n\nEvery `/v1/admin/*` route, 1:1. Requires a key whose user has type `\"admin\"` — anything else gets `ADMIN_REQUIRED`. Never ship an admin key to a browser; call these server-side (or behind a server-side proxy).\n\n```ts\n// Keys\nconst { data: keys } = await agency.admin.keys.list(); // + owner email/name\nconst { data: created } = await agency.admin.keys.create({\n  userId: \"user-id\", // or email: \"client@acme.com\"\n  type: \"server\", // default \"public\"\n});\ncreated.key; // full value — returned only here and via reveal\nawait agency.admin.keys.reveal(created.id); // { key } — 410 if revoked\nawait agency.admin.keys.revoke(created.id); // soft; { permanent: true } deletes\n\n// Users (API user = portfolio account + API settings)\nconst { data: users } = await agency.admin.users.list();\nconst { data: user } = await agency.admin.users.get(\"user-id\"); // 200 with null fields if no settings yet\nconst { data: full } = await agency.admin.users.lookup(\"client@acme.com\"); // + active keys, decrypted\nawait agency.admin.users.create({\n  email: \"client@acme.com\",\n  bucketName: \"acme-media\", // verified to exist in R2\n  publicBaseUrl: \"https://media.acme.com\", // verified to serve that bucket\n  emailDomain: \"acme.com\", // verified in SES\n  allowedOrigins: [\"acme.com\"],\n}); // auto-mints a key, returned once as .apiKey\nawait agency.admin.users.update(\"user-id\", { emailDomain: \"acme.com\" }); // settings upsert + same verification\nawait agency.admin.users.delete(\"user-id\"); // removes API access, keeps the account\n\n// Email usage (per user — the admin counterpart of agency.emails.list())\nconst { data: usage } = await agency.admin.emailLogs.list({\n  userId: \"user-id\",\n  limit: 10,\n});\nusage.stats; // { total, thisMonth, send, contact, lastSentAt }\n\n// Env backups (metadata only; content requires the vault password)\nconst { data: envs } = await agency.admin.envs.list({ email: \"client@acme.com\" });\nconst { data: dotenv } = await agency.admin.envs.reveal(\"env-id\", \"vault-password\"); // raw .env text\n\n// Health\nawait agency.admin.sesHealth(); // SES account/identities/statistics\nawait agency.admin.health(); // live Neon/KV/SES/R2 probe (503 when degraded)\n```\n\nConfig edits are verified server-side before they're saved: a missing bucket, an unreachable public URL, or an unverified SES domain fails with `BUCKET_NOT_FOUND`, `PUBLIC_URL_UNREACHABLE` / `PUBLIC_URL_NOT_SERVING` / `PUBLIC_URL_WRONG_BUCKET`, or `EMAIL_DOMAIN_NOT_VERIFIED`.\n\n## Errors\n\n`error` is an `AgencyError` with:\n\n| field       | meaning                                |\n| ----------- | -------------------------------------- |\n| `status`    | HTTP status (`0` for network failures) |\n| `code`      | stable identifier, safe to branch on   |\n| `message`   | human-readable, one line               |\n| `causeHint` | optional: why it happened / how to fix |\n\n`code` is typed as `AgencyErrorCode` — a union of every code the API returns, so you get autocomplete when branching:\n\n```ts\nif (error.code === \"FILE_ALREADY_EXISTS\") {\n  /* ... */\n}\n```\n\nCommon codes: `MISSING_API_KEY`, `UNKNOWN_API_KEY`, `API_KEY_REVOKED`, `VALIDATION_FAILED`, `RATE_LIMIT_EXCEEDED` (contact form, 5 per 10 min per IP), `SENDER_DOMAIN_MISMATCH`, `EMAIL_DOMAIN_NOT_CONFIGURED`, `BUCKET_NOT_CONFIGURED`, `FILE_ALREADY_EXISTS`, `OBJECT_NOT_FOUND`, `NETWORK_ERROR`.\n\n## Limits\n\n- Uploads: 50 MB max per file; presigned URLs expire after 15 minutes.\n- Emails: `from` must be on your configured domain (`send`); `sendContact` is limited to 5 requests per 10 minutes per IP.\n","readmeFilename":"README.md"}