faxforagents 0.0.0-stage → 0.2.2

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/CHANGELOG.md ADDED
@@ -0,0 +1,39 @@
1
+ # Changelog
2
+
3
+ ## 0.2.2 (2026-10-30)
4
+
5
+ First version on the npm registry. The README opens with the Fax for Agents logo, a link row to the
6
+ website, quickstart, API reference, SDK docs, MCP page, dashboard, pricing and changelog, and badges
7
+ for the npm version, CI, licence, Node and TypeScript. No client code changed.
8
+
9
+ ## 0.2.1 (2026-10-29)
10
+
11
+ API version 1.2.3. The generated types document `503 live_provider_unavailable` on the eight operations
12
+ that reach the carrier with a live key (`createFaxQuote`, `createFax`, `cancelFax`, `getNumberInventory`,
13
+ `createNumberOrder`, `createReleaseRequest`, `createPortabilityCheck`, `createPortOrder`). A production
14
+ server with no carrier configured refuses them before any hold or approval is consumed, with `retryable`
15
+ false. No client code changed.
16
+
17
+ ## 0.2.0 (2026-10-28)
18
+
19
+ API version 1.1.0: HTML rendering and image uploads.
20
+
21
+ - `documents.create({ html })` renders HTML on the server, scripts off and no network.
22
+ - `documents.upload` takes a PNG, JPG or TIFF beside a PDF and reads the content type from the
23
+ filename (`guessContentType`, `CONTENT_TYPES`). `createUpload` documents the four content types.
24
+ - New resources, every operation of the document: `numbers` (coverage, inventory, orders, porting,
25
+ sender verification), `extractions` (OCR, fields, classification, summaries, saved schemas),
26
+ `organizations` and `members`. The inbox gains `update`, `delete`, `getDownload` and `download`.
27
+ - `sandbox.createInboundFax` returns `InboxItemSummary`. `InboxItem` carries the number, project,
28
+ media status and read state of a received fax. `Quote` carries `per_page_micro` and `route_label`.
29
+ - A `prepare` script builds the package on a git install.
30
+
31
+ ## 0.1.0 (2026-10-28)
32
+
33
+ First release.
34
+
35
+ - `FaxForAgents` client over `fetch`, every `/v1` operation of API version 0.1.0, ESM and CommonJS.
36
+ - Types generated from the public OpenAPI document with openapi-typescript (`npm run gen:types`).
37
+ - `Idempotency-Key` on every mutating call, retries for 429 and 5xx with `Retry-After`.
38
+ - `iter` helpers on every list, `faxes.wait` and `approvals.wait`.
39
+ - `verifyWebhook` for the Standard Webhooks signature, with rotation support, on Web Crypto.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 JSB Holdings LLC
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 all
13
+ 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 THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,197 @@
1
- # Temporary Holding Version
1
+ <p align="center">
2
+ <a href="https://faxforagents.com"><img src="https://faxforagents.com/brand/logo-512.png" width="88" alt="Fax for Agents"></a>
3
+ </p>
2
4
 
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.
5
+ <h1 align="center">faxforagents</h1>
6
+
7
+ <p align="center">The TypeScript and JavaScript client for <a href="https://faxforagents.com">Fax for Agents</a>, the fax API built for AI agents.</p>
8
+
9
+ <p align="center">
10
+ <a href="https://faxforagents.com">Website</a> ·
11
+ <a href="https://faxforagents.com/docs/quickstart/">Quickstart</a> ·
12
+ <a href="https://faxforagents.com/docs/api/">API reference</a> ·
13
+ <a href="https://faxforagents.com/docs/sdks/">SDKs</a> ·
14
+ <a href="https://faxforagents.com/mcp/">MCP</a> ·
15
+ <a href="https://app.faxforagents.com">Dashboard</a> ·
16
+ <a href="https://faxforagents.com/pricing/">Pricing</a> ·
17
+ <a href="https://faxforagents.com/changelog/">Changelog</a>
18
+ </p>
19
+
20
+ <p align="center">
21
+ <a href="https://www.npmjs.com/package/faxforagents"><img src="https://img.shields.io/npm/v/faxforagents?label=npm" alt="npm version"></a>
22
+ <a href="https://github.com/faxforagents/sdk-typescript/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/faxforagents/sdk-typescript/ci.yml?branch=main&label=ci" alt="CI"></a>
23
+ <a href="https://github.com/faxforagents/sdk-typescript/blob/main/LICENSE"><img src="https://img.shields.io/badge/licence-MIT-1f6feb" alt="MIT licence"></a>
24
+ <a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-18%2B-339933" alt="Node 18+"></a>
25
+ <a href="https://www.typescriptlang.org"><img src="https://img.shields.io/badge/types-included-3178c6" alt="TypeScript"></a>
26
+ </p>
27
+
28
+ Fax for Agents is a fax API, a hosted MCP server and SDKs built so AI agents can send and receive
29
+ faxes. It is made by JSB Holdings LLC.
30
+
31
+ ```bash
32
+ npm install faxforagents
33
+ ```
34
+
35
+ Node 18 or later, Deno, Bun, browsers and edge runtimes. Zero runtime dependencies. The client uses
36
+ `fetch` and Web Crypto. ESM and CommonJS builds, types included.
37
+
38
+ ## Quickstart, against the sandbox
39
+
40
+ A test key (`ffa_test_...`) reaches the sandbox provider only. No carrier, no cost, nothing leaves the
41
+ box. The destination number picks the outcome. Keys are created in the dashboard at
42
+ <https://app.faxforagents.com> or with `POST /v1/api-keys`.
43
+
44
+ ```ts
45
+ import { FaxForAgents } from 'faxforagents';
46
+
47
+ const ffa = new FaxForAgents(); // reads FAXFORAGENTS_API_KEY
48
+
49
+ const doc = await ffa.documents.create({ text: 'Hello from an agent.', filename: 'hello' });
50
+ console.log(doc.id, doc.page_count, doc.sha256.slice(0, 12));
51
+
52
+ const quote = await ffa.quotes.create({ document_id: doc.id, to: '+15550000001' });
53
+ console.log(quote.amount_micro, 'micro, expires', quote.expires_at);
54
+
55
+ let fax = await ffa.faxes.create({ quote_id: quote.id }); // Idempotency-Key minted for you
56
+ console.log(fax.id, fax.state); // queued, never delivered yet
57
+
58
+ fax = await ffa.faxes.wait(fax.id); // polls until a terminal state
59
+ console.log(fax.state, fax.pages_sent, fax.evidence); // delivered, 1, {...}
60
+
61
+ for await (const job of ffa.faxes.iter({ state: 'failed' })) { // follows next_cursor
62
+ console.log(job.id, job.failure_code);
63
+ }
64
+ ```
65
+
66
+ ## What the client does for you
67
+
68
+ - Every mutating call carries an `Idempotency-Key`. When you pass none, a UUID is minted once per call
69
+ and reused on every retry, so a retried send never creates a second fax. Pass
70
+ `{ idempotencyKey }` as the last argument to pick your own.
71
+ - 429 and 5xx answers are retried up to three times. `Retry-After` is honoured. Network errors and
72
+ timeouts are retried the same way.
73
+ - Every list has an `iter` twin that follows `next_cursor`, as an async iterator.
74
+ - `documents.create({ text })`, `{ markdown }` or `{ html }` renders on the server. HTML prints with
75
+ scripts off and no network, inline CSS and `data:` images only, at most 2 MiB.
76
+ - `documents.upload(bytes, { filename })` runs the whole upload path for a PDF or an image (PNG, JPG,
77
+ TIFF): the upload session, the signed PUT with the content type read from the filename, the sha256
78
+ check, the document. An image becomes gray letter pages.
79
+ - `faxes.wait(faxId)` and `approvals.wait(approvalId)` poll with a timeout.
80
+ - `verifyWebhook(secret, headers, body)` checks the Standard Webhooks signature on a delivery.
81
+ - Types are generated from the public OpenAPI document with openapi-typescript. Money is an integer
82
+ count of USD micro-units (`39000` is $0.039). Timestamps are UTC strings.
83
+
84
+ ## Resources
85
+
86
+ Method names are the operationIds of the [OpenAPI document](https://github.com/faxforagents/openapi)
87
+ in camel case, shortened by their resource. The reference at <https://faxforagents.github.io/openapi/>
88
+ names the scope each call needs.
89
+
90
+ | Resource | Calls |
91
+ |---|---|
92
+ | `ffa.identity` | `me`, `listApiKeys`, `createApiKey`, `rotateApiKey`, `revokeApiKey` |
93
+ | `ffa.documents` | `create`, `upload`, `createUpload`, `putUploadContent`, `completeUpload`, `cancelUpload`, `list`, `iter`, `get`, `delete`, `getValidation`, `getDownload`, `download`, `listPages` |
94
+ | `ffa.quotes` | `create`, `get` |
95
+ | `ffa.faxes` | `create`, `list`, `iter`, `get`, `wait`, `listEvents`, `listAttempts`, `getReceipt`, `cancel` |
96
+ | `ffa.webhooks` | `list`, `create`, `update`, `delete`, `rotateSecret`, `test`, `listDeliveries`, `replayDelivery` |
97
+ | `ffa.events` | `list`, `iter` |
98
+ | `ffa.billing` | `balance`, `listLedger`, settings, top-ups, auto top-ups, budgets, `usage`, exports, invoices, subscriptions, `createPortalSession` |
99
+ | `ffa.platform` | `capabilities`, `serviceStatus` |
100
+ | `ffa.sandbox` | `listScenarios`, `createScenario`, `createInboundFax`, `reset` |
101
+ | `ffa.approvals` | `request`, `requestHelp`, `list`, `iter`, `get`, `wait`, `approve`, `reject`, `revoke` |
102
+ | `ffa.policies` | `list`, `create`, `effective`, `get`, `update`, `listVersions`, `evaluate` |
103
+ | `ffa.agents` | `list`, `create`, `get`, `update`, `createKey`, `activity` |
104
+ | `ffa.inbox` | `list`, `iter`, `get`, `update`, `delete`, `getDownload`, `download` |
105
+ | `ffa.numbers` | `coverage`, `inventory`, `createOrder`, `getOrder`, `list`, `get`, `update`, `release`, `checkPortability`, `listPortOrders`, `createPortOrder`, `getPortOrder`, `createPortOutRequest`, `verifySender` |
106
+ | `ffa.extractions` | `create`, `list`, `iter`, `get`, `correct`, `classify`, `listClassifications`, `iterClassifications`, `getClassification`, `summarize`, `listSummaries`, `iterSummaries`, `getSummary`, `listSchemas`, `createSchema`, `getSchema` |
107
+ | `ffa.organizations` | `list`, `current`, `updateCurrent`, `requestDataExport`, `requestDataDeletion` |
108
+ | `ffa.members` | `list`, `update`, `remove`, `listInvitations`, `invite`, `revokeInvitation` |
109
+
110
+ `ffa.request('GET', '/v1/anything')` reaches an operation the resources do not cover yet.
111
+
112
+ ## States
113
+
114
+ A fax job is `queued`, `active`, `partial`, `failed`, `unknown` or `delivered`. `delivered` is written
115
+ only when the carrier's evidence is on the attempt, and `fax.evidence` holds it. `partial` and
116
+ `unknown` never retransmit on their own. Whether to resend is a human decision.
117
+
118
+ Sandbox destinations: `+15550000001` delivered, `+15550000002` busy then delivered, `+15550000003`
119
+ partial, `+15550000004` no answer, `+15550000005` unknown, `+15550000006` provider timeout,
120
+ `+15550000007` invalid number. Any other `+1` number is delivered.
121
+
122
+ ## Errors
123
+
124
+ ```ts
125
+ import { APIError, RateLimitedError } from 'faxforagents';
126
+
127
+ try {
128
+ await ffa.faxes.create({ quote_id: quote.id });
129
+ } catch (err) {
130
+ if (err instanceof RateLimitedError) console.log('retry in', err.retryAfter);
131
+ else if (err instanceof APIError) console.log(err.code, err.message, err.correlationId);
132
+ }
133
+ ```
134
+
135
+ `AuthenticationError` (401), `ScopeError` (403), `NotFoundError` (404), `ConflictError` (409),
136
+ `PaymentRequiredError` (402), `InvalidRequestError` (400, 422), `RateLimitedError` (429) and
137
+ `ServerError` (5xx) all extend `APIError`. `APIConnectionError` and `APITimeoutError` mean the API was
138
+ not reached.
139
+
140
+ ## Approvals
141
+
142
+ A live send needs either a human approval bound to the quote or a delegated policy that allows it.
143
+
144
+ ```ts
145
+ let req = await ffa.approvals.request(quote.id); // a person is mailed
146
+ req = await ffa.approvals.wait(req.id); // pending until they decide
147
+ if (req.status === 'approved') {
148
+ await ffa.faxes.create({ quote_id: quote.id, approval_id: req.id });
149
+ }
150
+ ```
151
+
152
+ An agent's own API key can never approve. `ffa.policies.evaluate({ quote_id })` is a dry run that
153
+ says whether a policy would allow the send.
154
+
155
+ ## Webhooks
156
+
157
+ ```ts
158
+ import { verifyWebhook, parseEvent, SignatureError } from 'faxforagents';
159
+
160
+ // Express: app.post('/hooks/fax', express.raw({ type: '*/*' }), async (req, res) => { ... })
161
+ try {
162
+ const eventId = await verifyWebhook(secret, req.headers, req.body); // raw bytes
163
+ const event = parseEvent(req.body); // event.type: fax.delivered...
164
+ res.sendStatus(200);
165
+ } catch (err) {
166
+ if (err instanceof SignatureError) res.sendStatus(400);
167
+ }
168
+ ```
169
+
170
+ Verify on the raw bytes. `verifyWebhook` is async because it uses Web Crypto. Store the event id to
171
+ drop a redelivery you already handled. During a secret rotation two signatures arrive for 24 hours and
172
+ either one verifies.
173
+
174
+ ## Prices
175
+
176
+ Price card launch-v1 is effective from 2026-10-28. $0.039 per page sent, $0.019 per page received.
177
+ $2 per number per month, $19 per month for the Agent workspace. Sandbox pages cost 0.
178
+ `ffa.platform.capabilities()` returns the card in force.
179
+
180
+ ## Working on this repository
181
+
182
+ ```bash
183
+ npm ci
184
+ npm test # vitest with msw, no network
185
+ FAXFORAGENTS_API_KEY=ffa_test_... npm run test:live # one real sandbox send
186
+ npm run gen:types # src/schema.d.ts from spec/openapi.yaml
187
+ npm run typecheck && npm run build
188
+ sh scripts/truthcheck.sh
189
+ ```
190
+
191
+ `spec/openapi.yaml` is a copy of the public document. To take a new one, copy it over and run
192
+ `npm run gen:types`. `npm install` from a git URL builds the package on install (the `prepare` script),
193
+ so `npm install github:faxforagents/sdk-typescript` works before the package is on npm.
194
+
195
+ ## Licence
196
+
197
+ MIT. See [LICENSE](LICENSE). Security reports go to hello@faxforagents.com, see [SECURITY.md](SECURITY.md).