inboxjot 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) Arik Chakma
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,147 @@
1
- # Temporary Holding Version
1
+ ![Inboxjot](https://inboxjot.com/og.png)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ <p align="center">The official Node.js SDK for the Inboxjot email API. <br />Email for builders and their agents.</p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/inboxjot"><img src="https://inboxjot.com/badges/npm.svg?v=2" alt="npm" height="24" /></a>
7
+ <a href="./LICENSE"><img src="https://inboxjot.com/badges/license.svg?v=2" alt="License" height="24" /></a>
8
+ <a href="https://inboxjot.com/docs"><img src="https://inboxjot.com/badges/docs.svg?v=2" alt="Docs" height="24" /></a>
9
+ </p>
10
+
11
+ Send email, manage contacts, campaigns, templates and domains, and verify webhooks from your Node.js app. The SDK has no runtime dependencies. It uses the global `fetch` and Web Crypto, so it runs on Node 18+, Bun, Deno and Cloudflare Workers.
12
+
13
+ ### Quick Start
14
+
15
+ ```sh
16
+ npm install inboxjot
17
+ ```
18
+
19
+ ```ts
20
+ import { Inboxjot } from 'inboxjot';
21
+
22
+ const inboxjot = new Inboxjot({ apiKey: 'ibx_...' });
23
+
24
+ const { id } = await inboxjot.emails.send({
25
+ from: 'Acme <hi@acme.dev>',
26
+ to: 'jane@example.com',
27
+ subject: 'Welcome',
28
+ html: '<p>Hi Jane</p>',
29
+ });
30
+ ```
31
+
32
+ Every option is optional. Without `apiKey`, the client reads `INBOXJOT_API_KEY` from the environment, so `new Inboxjot()` works. The other options are `baseUrl`, `timeout` (ms), `maxRetries` and a custom `fetch`.
33
+
34
+ ### Resources
35
+
36
+ ```ts
37
+ await inboxjot.emails.batch([{ from, to: 'a@example.com', subject, html }]);
38
+ await inboxjot.emails.list({ source: 'api', per_page: 50 });
39
+
40
+ const contact = await inboxjot.contacts.create({
41
+ email: 'jane@example.com',
42
+ first_name: 'Jane',
43
+ });
44
+ await inboxjot.contacts.update('jane@example.com', { last_name: 'Doe' });
45
+ await inboxjot.contacts.erase({ email: 'jane@example.com' });
46
+ await inboxjot.events.send({
47
+ name: 'signed_up',
48
+ email: 'jane@example.com',
49
+ data: { plan: 'pro' },
50
+ });
51
+
52
+ const campaign = await inboxjot.campaigns.create({
53
+ name: 'October',
54
+ subject: 'News',
55
+ from,
56
+ html,
57
+ });
58
+ await inboxjot.campaigns.send(campaign.id, {
59
+ scheduled_at: '2026-10-20T09:00:00Z',
60
+ });
61
+
62
+ const template = await inboxjot.templates.create({ name: 'Welcome', html });
63
+ await inboxjot.templates.publish(template.id);
64
+ await inboxjot.templates.delete(template.id);
65
+ ```
66
+
67
+ Path ids come first, then the body or query, then the request options. `contacts.get`, `update` and `delete` take a contact id or the contact's email.
68
+
69
+ An image that is already online goes straight into the content as `<img src="https://…">`. To host a PNG, JPEG or GIF of up to 5 MB on Inboxjot, upload it:
70
+
71
+ ```ts
72
+ const image = await inboxjot.images.upload({
73
+ file: await readFile('logo.png'),
74
+ file_name: 'logo.png',
75
+ });
76
+ ```
77
+
78
+ The client covers the whole public API: `emails`, `contacts`, `events`, `campaigns`, `templates`, `domains`, `images`, `segments`, `topics` and `webhooks`. The [API reference](https://inboxjot.com/docs) lists every endpoint and field.
79
+
80
+ ### Pagination
81
+
82
+ Lists page with a cursor. Pass `next_cursor` back as `after`. It is `null` on the last page. The client leaves a `null` cursor out of the request.
83
+
84
+ ```ts
85
+ let after: string | null = null;
86
+ do {
87
+ const page = await inboxjot.contacts.list({ per_page: 100, after });
88
+ console.log(page.data.length, page.total);
89
+ after = page.next_cursor;
90
+ } while (after);
91
+ ```
92
+
93
+ ### Idempotency and Retries
94
+
95
+ Every method takes request options as its last argument: `idempotencyKey`, `timeout`, `maxRetries` and `signal`.
96
+
97
+ ```ts
98
+ await inboxjot.emails.send(email, { idempotencyKey: `welcome-${user.id}` });
99
+ ```
100
+
101
+ The client retries with exponential backoff and honors `Retry-After`. A `429` always retries. A `5xx`, a timeout or a network error retries only for a `GET`, a `DELETE` or a request with an `idempotencyKey`, so an email is never sent twice. A `Retry-After` over 60 seconds, such as the daily sending limit, goes straight to the caller.
102
+
103
+ ### Errors
104
+
105
+ A failed request throws. An API error is an `InboxjotError` with a typed `name`, plus `status`, `message`, `errors` and `requestId`. A network error or timeout is an `InboxjotConnectionError`.
106
+
107
+ ```ts
108
+ import { InboxjotError } from 'inboxjot';
109
+
110
+ try {
111
+ await inboxjot.emails.get('em_...');
112
+ } catch (error) {
113
+ if (error instanceof InboxjotError && error.name === 'not_found') {
114
+ // ...
115
+ }
116
+ }
117
+ ```
118
+
119
+ ### Verify Webhooks
120
+
121
+ Inboxjot signs webhooks with the [Standard Webhooks](https://www.standardwebhooks.com) spec. Verify the raw body before you parse it:
122
+
123
+ ```ts
124
+ import { verifyWebhook } from 'inboxjot';
125
+
126
+ export async function POST(request: Request) {
127
+ const event = await verifyWebhook({
128
+ payload: await request.text(),
129
+ headers: request.headers,
130
+ secret: process.env.INBOXJOT_WEBHOOK_SECRET!,
131
+ });
132
+ if (event.type === 'email.bounced') {
133
+ console.log(event.data.email_id, event.data.bounce.type);
134
+ }
135
+ return new Response(null, { status: 204 });
136
+ }
137
+ ```
138
+
139
+ `inboxjot.webhooks.verify` takes the same object. A bad signature, a missing header or a timestamp more than 5 minutes off throws a `WebhookVerificationError`.
140
+
141
+ ### Contributing
142
+
143
+ The types in `src/schema.ts` are generated from the public part of the Inboxjot OpenAPI spec with `pnpm generate`. Run `pnpm check`, `pnpm test` and `pnpm build` before you open a pull request.
144
+
145
+ ### License
146
+
147
+ [MIT](./LICENSE) &copy; [Arik Chakma](https://x.com/imarikchakma)