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 +39 -0
- package/LICENSE +21 -0
- package/README.md +196 -2
- package/dist/index.cjs +1138 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +13363 -0
- package/dist/index.d.ts +13363 -0
- package/dist/index.js +1069 -0
- package/dist/index.js.map +1 -0
- package/package.json +75 -4
package/dist/index.js
ADDED
|
@@ -0,0 +1,1069 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var FaxForAgentsError = class extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = new.target.name;
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
var APIConnectionError = class extends FaxForAgentsError {
|
|
9
|
+
};
|
|
10
|
+
var APITimeoutError = class extends APIConnectionError {
|
|
11
|
+
};
|
|
12
|
+
var APIError = class extends FaxForAgentsError {
|
|
13
|
+
status;
|
|
14
|
+
code;
|
|
15
|
+
retryable;
|
|
16
|
+
correlationId;
|
|
17
|
+
details;
|
|
18
|
+
/** Seconds the API asked us to wait (429), when it said. */
|
|
19
|
+
retryAfter;
|
|
20
|
+
constructor(f) {
|
|
21
|
+
super(`${f.code}: ${f.message}${f.correlationId ? ` (correlation ${f.correlationId})` : ""}`);
|
|
22
|
+
this.status = f.status;
|
|
23
|
+
this.code = f.code;
|
|
24
|
+
this.retryable = f.retryable ?? false;
|
|
25
|
+
this.correlationId = f.correlationId ?? null;
|
|
26
|
+
this.details = f.details;
|
|
27
|
+
this.retryAfter = f.retryAfter ?? null;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var InvalidRequestError = class extends APIError {
|
|
31
|
+
};
|
|
32
|
+
var AuthenticationError = class extends APIError {
|
|
33
|
+
};
|
|
34
|
+
var PaymentRequiredError = class extends APIError {
|
|
35
|
+
};
|
|
36
|
+
var ScopeError = class extends APIError {
|
|
37
|
+
};
|
|
38
|
+
var NotFoundError = class extends APIError {
|
|
39
|
+
};
|
|
40
|
+
var ConflictError = class extends APIError {
|
|
41
|
+
};
|
|
42
|
+
var RateLimitedError = class extends APIError {
|
|
43
|
+
};
|
|
44
|
+
var ServerError = class extends APIError {
|
|
45
|
+
};
|
|
46
|
+
var BY_STATUS = {
|
|
47
|
+
400: InvalidRequestError,
|
|
48
|
+
401: AuthenticationError,
|
|
49
|
+
402: PaymentRequiredError,
|
|
50
|
+
403: ScopeError,
|
|
51
|
+
404: NotFoundError,
|
|
52
|
+
409: ConflictError,
|
|
53
|
+
422: InvalidRequestError,
|
|
54
|
+
429: RateLimitedError
|
|
55
|
+
};
|
|
56
|
+
function errorFor(status, payload, opts = {}) {
|
|
57
|
+
const body = payload && typeof payload === "object" ? payload : null;
|
|
58
|
+
let err = body && body.error && typeof body.error === "object" ? body.error : null;
|
|
59
|
+
if (!err) {
|
|
60
|
+
err = {
|
|
61
|
+
code: `http_${status}`,
|
|
62
|
+
message: (opts.text ?? "").slice(0, 200) || `HTTP ${status}`,
|
|
63
|
+
details: body?.detail
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const Cls = status >= 500 ? ServerError : BY_STATUS[status] ?? APIError;
|
|
67
|
+
return new Cls({
|
|
68
|
+
status,
|
|
69
|
+
code: String(err.code ?? `http_${status}`),
|
|
70
|
+
message: String(err.message ?? `HTTP ${status}`),
|
|
71
|
+
retryable: typeof err.retryable === "boolean" ? err.retryable : [429, 502, 503, 504].includes(status),
|
|
72
|
+
correlationId: typeof err.correlation_id === "string" ? err.correlation_id : null,
|
|
73
|
+
details: err.details,
|
|
74
|
+
retryAfter: opts.retryAfter ?? null
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/version.ts
|
|
79
|
+
var VERSION = "0.2.2";
|
|
80
|
+
|
|
81
|
+
// src/http.ts
|
|
82
|
+
var DEFAULT_BASE_URL = "https://api.faxforagents.com";
|
|
83
|
+
var MUTATING = /* @__PURE__ */ new Set(["POST", "PATCH", "DELETE"]);
|
|
84
|
+
var RETRY_STATUSES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
85
|
+
function env(name) {
|
|
86
|
+
const g = globalThis;
|
|
87
|
+
return g.process?.env?.[name];
|
|
88
|
+
}
|
|
89
|
+
function resolveKey(key) {
|
|
90
|
+
const value = (key ?? env("FAXFORAGENTS_API_KEY") ?? env("FFA_API_KEY") ?? "").trim();
|
|
91
|
+
if (!value) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
"no API key: pass apiKey or set FAXFORAGENTS_API_KEY. Keys are created in the Fax for Agents dashboard or with POST /v1/api-keys."
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
function retryAfterSeconds(value, cap) {
|
|
99
|
+
if (!value) return null;
|
|
100
|
+
const n = Number(value.trim());
|
|
101
|
+
if (Number.isFinite(n)) return Math.min(Math.max(n, 0), cap);
|
|
102
|
+
const at = Date.parse(value);
|
|
103
|
+
if (Number.isNaN(at)) return null;
|
|
104
|
+
return Math.max(0, Math.min((at - Date.now()) / 1e3, cap));
|
|
105
|
+
}
|
|
106
|
+
function cleanParams(params) {
|
|
107
|
+
if (!params) return "";
|
|
108
|
+
const q = new URLSearchParams();
|
|
109
|
+
for (const [k, v] of Object.entries(params)) {
|
|
110
|
+
if (v !== null && v !== void 0) q.set(k, String(v));
|
|
111
|
+
}
|
|
112
|
+
const s = q.toString();
|
|
113
|
+
return s ? `?${s}` : "";
|
|
114
|
+
}
|
|
115
|
+
function stripNulls(json) {
|
|
116
|
+
if (!json || typeof json !== "object" || Array.isArray(json)) return json;
|
|
117
|
+
const out = {};
|
|
118
|
+
for (const [k, v] of Object.entries(json)) {
|
|
119
|
+
if (v !== void 0 && v !== null) out[k] = v;
|
|
120
|
+
}
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
123
|
+
var sleep = (s) => new Promise((r) => setTimeout(r, Math.max(0, s * 1e3)));
|
|
124
|
+
var Http = class {
|
|
125
|
+
baseUrl;
|
|
126
|
+
apiKey;
|
|
127
|
+
timeoutMs;
|
|
128
|
+
maxRetries;
|
|
129
|
+
backoffBase;
|
|
130
|
+
maxRetryAfter;
|
|
131
|
+
fetchImpl;
|
|
132
|
+
extraHeaders;
|
|
133
|
+
constructor(opts = {}) {
|
|
134
|
+
this.apiKey = resolveKey(opts.apiKey);
|
|
135
|
+
this.baseUrl = (opts.baseUrl ?? env("FAXFORAGENTS_API_URL") ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
136
|
+
this.timeoutMs = opts.timeoutMs ?? 6e4;
|
|
137
|
+
this.maxRetries = Math.max(0, opts.maxRetries ?? 3);
|
|
138
|
+
this.backoffBase = opts.backoffBase ?? 0.5;
|
|
139
|
+
this.maxRetryAfter = opts.maxRetryAfter ?? 30;
|
|
140
|
+
this.fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
141
|
+
this.extraHeaders = opts.headers ?? {};
|
|
142
|
+
}
|
|
143
|
+
waitFor(attempt, retryAfter) {
|
|
144
|
+
const explicit = retryAfterSeconds(retryAfter, this.maxRetryAfter);
|
|
145
|
+
if (explicit !== null) return explicit;
|
|
146
|
+
return Math.random() * this.backoffBase * 2 ** attempt;
|
|
147
|
+
}
|
|
148
|
+
/** The raw Response of a successful call. Throws APIError on 4xx/5xx after the retries. */
|
|
149
|
+
async send(method, path, opts = {}) {
|
|
150
|
+
const m = method.toUpperCase();
|
|
151
|
+
const url = (path.startsWith("http") ? path : this.baseUrl + path) + cleanParams(opts.params);
|
|
152
|
+
const headers = {
|
|
153
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
154
|
+
Accept: "application/json",
|
|
155
|
+
"User-Agent": `faxforagents-js/${VERSION}`,
|
|
156
|
+
...this.extraHeaders,
|
|
157
|
+
...opts.headers ?? {}
|
|
158
|
+
};
|
|
159
|
+
let body = opts.body;
|
|
160
|
+
if (opts.json !== void 0) {
|
|
161
|
+
headers["Content-Type"] = "application/json";
|
|
162
|
+
body = JSON.stringify(stripNulls(opts.json));
|
|
163
|
+
}
|
|
164
|
+
if (MUTATING.has(m) && !("Idempotency-Key" in headers)) {
|
|
165
|
+
headers["Idempotency-Key"] = opts.idempotencyKey ?? crypto.randomUUID();
|
|
166
|
+
}
|
|
167
|
+
let attempt = 0;
|
|
168
|
+
for (; ; ) {
|
|
169
|
+
const controller = new AbortController();
|
|
170
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
171
|
+
let resp;
|
|
172
|
+
try {
|
|
173
|
+
resp = await this.fetchImpl(url, { method: m, headers, body, signal: controller.signal });
|
|
174
|
+
} catch (err) {
|
|
175
|
+
clearTimeout(timer);
|
|
176
|
+
const timedOut = err?.name === "AbortError";
|
|
177
|
+
if (attempt >= this.maxRetries) {
|
|
178
|
+
if (timedOut) throw new APITimeoutError(`${m} ${path} timed out after ${this.timeoutMs} ms`);
|
|
179
|
+
throw new APIConnectionError(`${this.baseUrl} not reachable (${err?.message ?? err})`);
|
|
180
|
+
}
|
|
181
|
+
await sleep(this.waitFor(attempt, null));
|
|
182
|
+
attempt += 1;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
clearTimeout(timer);
|
|
186
|
+
if (RETRY_STATUSES.has(resp.status) && attempt < this.maxRetries) {
|
|
187
|
+
await resp.text().catch(() => void 0);
|
|
188
|
+
await sleep(this.waitFor(attempt, resp.headers.get("retry-after")));
|
|
189
|
+
attempt += 1;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (resp.status >= 400) {
|
|
193
|
+
const text = await resp.text();
|
|
194
|
+
let payload = null;
|
|
195
|
+
try {
|
|
196
|
+
payload = JSON.parse(text);
|
|
197
|
+
} catch {
|
|
198
|
+
payload = null;
|
|
199
|
+
}
|
|
200
|
+
throw errorFor(resp.status, payload, {
|
|
201
|
+
retryAfter: retryAfterSeconds(resp.headers.get("retry-after"), this.maxRetryAfter),
|
|
202
|
+
text
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return resp;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/** The parsed JSON of a successful call, typed by the caller. */
|
|
209
|
+
async request(method, path, opts = {}) {
|
|
210
|
+
const resp = await this.send(method, path, opts);
|
|
211
|
+
const ctype = resp.headers.get("content-type") ?? "";
|
|
212
|
+
if (resp.status === 204 || !ctype.startsWith("application/json")) {
|
|
213
|
+
const text = await resp.text();
|
|
214
|
+
return text ? JSON.parse(text) : {};
|
|
215
|
+
}
|
|
216
|
+
return await resp.json();
|
|
217
|
+
}
|
|
218
|
+
/** The bytes of a successful call (signed download URLs). */
|
|
219
|
+
async bytes(method, path, opts = {}) {
|
|
220
|
+
const resp = await this.send(method, path, opts);
|
|
221
|
+
return new Uint8Array(await resp.arrayBuffer());
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
async function* paginate(fetchPage) {
|
|
225
|
+
let cursor;
|
|
226
|
+
for (; ; ) {
|
|
227
|
+
const page = await fetchPage(cursor);
|
|
228
|
+
for (const item of page.items ?? []) yield item;
|
|
229
|
+
if (!page.next_cursor) return;
|
|
230
|
+
cursor = page.next_cursor;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// src/client.ts
|
|
235
|
+
var TERMINAL_STATES = /* @__PURE__ */ new Set(["delivered", "partial", "failed", "unknown"]);
|
|
236
|
+
var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
237
|
+
var CONTENT_TYPES = {
|
|
238
|
+
".pdf": "application/pdf",
|
|
239
|
+
".png": "image/png",
|
|
240
|
+
".jpg": "image/jpeg",
|
|
241
|
+
".jpeg": "image/jpeg",
|
|
242
|
+
".tif": "image/tiff",
|
|
243
|
+
".tiff": "image/tiff"
|
|
244
|
+
};
|
|
245
|
+
function guessContentType(filename) {
|
|
246
|
+
const dot = filename.lastIndexOf(".");
|
|
247
|
+
const suffix = dot >= 0 ? filename.slice(dot).toLowerCase() : "";
|
|
248
|
+
return CONTENT_TYPES[suffix] ?? "application/pdf";
|
|
249
|
+
}
|
|
250
|
+
async function sha256Hex(data) {
|
|
251
|
+
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
252
|
+
return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
253
|
+
}
|
|
254
|
+
var Resource = class {
|
|
255
|
+
constructor(h) {
|
|
256
|
+
this.h = h;
|
|
257
|
+
}
|
|
258
|
+
h;
|
|
259
|
+
};
|
|
260
|
+
var Identity = class extends Resource {
|
|
261
|
+
/** Who the key is: organization, project, environment, scopes. Scope: any. */
|
|
262
|
+
me() {
|
|
263
|
+
return this.h.request("GET", "/v1/me");
|
|
264
|
+
}
|
|
265
|
+
/** Keys of the organization, metadata only. Scope: key:admin. */
|
|
266
|
+
listApiKeys() {
|
|
267
|
+
return this.h.request("GET", "/v1/api-keys");
|
|
268
|
+
}
|
|
269
|
+
/** Create a key. The secret is in the answer once. Scope: key:admin. */
|
|
270
|
+
createApiKey(body, o = {}) {
|
|
271
|
+
return this.h.request("POST", "/v1/api-keys", { json: body, ...o });
|
|
272
|
+
}
|
|
273
|
+
/** A new secret. The old one works 24 more hours. Scope: key:admin. */
|
|
274
|
+
rotateApiKey(keyId, o = {}) {
|
|
275
|
+
return this.h.request("POST", `/v1/api-keys/${keyId}/rotate`, o);
|
|
276
|
+
}
|
|
277
|
+
/** Revoke a key at once. Scope: key:admin. */
|
|
278
|
+
revokeApiKey(keyId, o = {}) {
|
|
279
|
+
return this.h.request("DELETE", `/v1/api-keys/${keyId}`, o);
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
var Documents = class extends Resource {
|
|
283
|
+
/**
|
|
284
|
+
* An immutable document from one of upload_id, text, markdown or html. HTML is rendered with scripts off
|
|
285
|
+
* and no network, at most 2 MiB. Scope: document:write.
|
|
286
|
+
*/
|
|
287
|
+
create(body, o = {}) {
|
|
288
|
+
return this.h.request("POST", "/v1/documents", { json: body, ...o });
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Open an upload session with a signed PUT URL (25 MB, one hour). `content_type` is application/pdf,
|
|
292
|
+
* image/png, image/jpeg or image/tiff. Scope: document:write.
|
|
293
|
+
*/
|
|
294
|
+
createUpload(body, o = {}) {
|
|
295
|
+
return this.h.request("POST", "/v1/uploads", { json: body, ...o });
|
|
296
|
+
}
|
|
297
|
+
/** Send the bytes to the signed URL from createUpload. No scope, the link is the credential. */
|
|
298
|
+
putUploadContent(uploadUrl, data, contentType = "application/pdf") {
|
|
299
|
+
return this.h.request("PUT", uploadUrl, { body: data, headers: { "Content-Type": contentType } });
|
|
300
|
+
}
|
|
301
|
+
/** Finalize an upload. The size and, when given, the sha256 are checked. Scope: document:write. */
|
|
302
|
+
completeUpload(uploadId, body = {}, o = {}) {
|
|
303
|
+
return this.h.request("POST", `/v1/uploads/${uploadId}/complete`, { json: body, ...o });
|
|
304
|
+
}
|
|
305
|
+
/** Cancel an incomplete upload. Scope: document:write. */
|
|
306
|
+
cancelUpload(uploadId, o = {}) {
|
|
307
|
+
return this.h.request("DELETE", `/v1/uploads/${uploadId}`, o);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* The whole upload path for a PDF or an image (PNG, JPG or TIFF): createUpload, put the bytes, complete
|
|
311
|
+
* with the sha256, create the document. The content type is read from the filename when not given. An
|
|
312
|
+
* image becomes gray letter pages.
|
|
313
|
+
*/
|
|
314
|
+
async upload(data, opts = {}) {
|
|
315
|
+
const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
|
|
316
|
+
const filename = opts.filename ?? "document.pdf";
|
|
317
|
+
const contentType = opts.contentType ?? guessContentType(filename);
|
|
318
|
+
const session = await this.createUpload({ filename, size_bytes: bytes.byteLength, content_type: contentType });
|
|
319
|
+
if (!session.upload_url) throw new Error("the upload session carries no upload_url");
|
|
320
|
+
await this.putUploadContent(session.upload_url, bytes, contentType);
|
|
321
|
+
await this.completeUpload(session.id, { sha256: await sha256Hex(bytes) });
|
|
322
|
+
return this.create({ upload_id: session.id, filename });
|
|
323
|
+
}
|
|
324
|
+
/** Documents, newest first. Scope: document:read. */
|
|
325
|
+
list(p = {}) {
|
|
326
|
+
return this.h.request("GET", "/v1/documents", { params: p });
|
|
327
|
+
}
|
|
328
|
+
/** Every document, following next_cursor. */
|
|
329
|
+
iter(p = {}) {
|
|
330
|
+
return paginate((cursor) => this.list({ ...p, cursor }));
|
|
331
|
+
}
|
|
332
|
+
/** Hash, pages and validation state. Scope: document:read. */
|
|
333
|
+
get(documentId) {
|
|
334
|
+
return this.h.request("GET", `/v1/documents/${documentId}`);
|
|
335
|
+
}
|
|
336
|
+
/** Delete the document, its bytes and its previews. Scope: document:write. */
|
|
337
|
+
delete(documentId, o = {}) {
|
|
338
|
+
return this.h.request("DELETE", `/v1/documents/${documentId}`, o);
|
|
339
|
+
}
|
|
340
|
+
/** Validation warnings. Scope: document:read. */
|
|
341
|
+
getValidation(documentId) {
|
|
342
|
+
return this.h.request("GET", `/v1/documents/${documentId}/validation`);
|
|
343
|
+
}
|
|
344
|
+
/** A signed download URL, valid ten minutes. Scope: document:read. */
|
|
345
|
+
getDownload(documentId) {
|
|
346
|
+
return this.h.request("GET", `/v1/documents/${documentId}/download`);
|
|
347
|
+
}
|
|
348
|
+
/** The document bytes (always a PDF), through a fresh signed URL. */
|
|
349
|
+
async download(documentId) {
|
|
350
|
+
const link = await this.getDownload(documentId);
|
|
351
|
+
return this.h.bytes("GET", link.url);
|
|
352
|
+
}
|
|
353
|
+
/** Rendered pages with signed preview URLs. Scope: document:read. */
|
|
354
|
+
listPages(documentId) {
|
|
355
|
+
return this.h.request("GET", `/v1/documents/${documentId}/pages`);
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
var Quotes = class extends Resource {
|
|
359
|
+
/** The exact price of one document to one E.164 destination, valid ten minutes. Scope: fax:quote. */
|
|
360
|
+
create(body, o = {}) {
|
|
361
|
+
return this.h.request("POST", "/v1/fax-quotes", { json: body, ...o });
|
|
362
|
+
}
|
|
363
|
+
/** Read a quote. Scope: fax:quote. */
|
|
364
|
+
get(quoteId) {
|
|
365
|
+
return this.h.request("GET", `/v1/fax-quotes/${quoteId}`);
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
var Faxes = class extends Resource {
|
|
369
|
+
/** Send a quoted fax. The answer is queued, never delivered. Poll `wait`. Scope: fax:send. */
|
|
370
|
+
create(body, o = {}) {
|
|
371
|
+
return this.h.request("POST", "/v1/faxes", { json: body, ...o });
|
|
372
|
+
}
|
|
373
|
+
/** Fax jobs, newest first. Scope: fax:read. */
|
|
374
|
+
list(p = {}) {
|
|
375
|
+
return this.h.request("GET", "/v1/faxes", { params: p });
|
|
376
|
+
}
|
|
377
|
+
/** Every fax job, following next_cursor. */
|
|
378
|
+
iter(p = {}) {
|
|
379
|
+
return paginate((cursor) => this.list({ ...p, cursor }));
|
|
380
|
+
}
|
|
381
|
+
/** The job with its evidence once delivered or partial. Scope: fax:read. */
|
|
382
|
+
get(faxId) {
|
|
383
|
+
return this.h.request("GET", `/v1/faxes/${faxId}`);
|
|
384
|
+
}
|
|
385
|
+
/** Poll until the state is delivered, partial, failed or unknown. Returns the last job read. */
|
|
386
|
+
async wait(faxId, opts = {}) {
|
|
387
|
+
const deadline = Date.now() + (opts.timeoutMs ?? 3e5);
|
|
388
|
+
let job = await this.get(faxId);
|
|
389
|
+
while (!TERMINAL_STATES.has(job.state) && Date.now() < deadline) {
|
|
390
|
+
await sleep2(opts.intervalMs ?? 2e3);
|
|
391
|
+
job = await this.get(faxId);
|
|
392
|
+
}
|
|
393
|
+
return job;
|
|
394
|
+
}
|
|
395
|
+
/** Ordered events of one fax. Scope: fax:read. */
|
|
396
|
+
listEvents(faxId) {
|
|
397
|
+
return this.h.request("GET", `/v1/faxes/${faxId}/events`);
|
|
398
|
+
}
|
|
399
|
+
/** Attempt history. Scope: fax:read. */
|
|
400
|
+
listAttempts(faxId) {
|
|
401
|
+
return this.h.request("GET", `/v1/faxes/${faxId}/attempts`);
|
|
402
|
+
}
|
|
403
|
+
/** Delivery evidence as a receipt. Scope: fax:read. */
|
|
404
|
+
getReceipt(faxId) {
|
|
405
|
+
return this.h.request("GET", `/v1/faxes/${faxId}/receipt`);
|
|
406
|
+
}
|
|
407
|
+
/** Cancel while queued, best effort once sending. Scope: fax:cancel. */
|
|
408
|
+
cancel(faxId, o = {}) {
|
|
409
|
+
return this.h.request("POST", `/v1/faxes/${faxId}/cancel`, { json: {}, ...o });
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
var Webhooks = class extends Resource {
|
|
413
|
+
/** Registered destinations. Scope: webhook:admin. */
|
|
414
|
+
list() {
|
|
415
|
+
return this.h.request("GET", "/v1/webhooks");
|
|
416
|
+
}
|
|
417
|
+
/** Register a destination. The secret is in the answer once. Scope: webhook:admin. */
|
|
418
|
+
create(body, o = {}) {
|
|
419
|
+
return this.h.request("POST", "/v1/webhooks", { json: body, ...o });
|
|
420
|
+
}
|
|
421
|
+
/** Change url, description, event_types or status. Scope: webhook:admin. */
|
|
422
|
+
update(webhookId, body, o = {}) {
|
|
423
|
+
return this.h.request("PATCH", `/v1/webhooks/${webhookId}`, { json: body, ...o });
|
|
424
|
+
}
|
|
425
|
+
/** Remove a destination. Scope: webhook:admin. */
|
|
426
|
+
delete(webhookId, o = {}) {
|
|
427
|
+
return this.h.request("DELETE", `/v1/webhooks/${webhookId}`, o);
|
|
428
|
+
}
|
|
429
|
+
/** A new secret. The old one signs too for 24 hours. Scope: webhook:admin. */
|
|
430
|
+
rotateSecret(webhookId, o = {}) {
|
|
431
|
+
return this.h.request("POST", `/v1/webhooks/${webhookId}/rotate-secret`, o);
|
|
432
|
+
}
|
|
433
|
+
/** Send a signed webhook.test event to the destination. Scope: webhook:admin. */
|
|
434
|
+
test(webhookId, o = {}) {
|
|
435
|
+
return this.h.request("POST", `/v1/webhooks/${webhookId}/test`, { json: {}, ...o });
|
|
436
|
+
}
|
|
437
|
+
/** Delivery attempts. Scope: webhook:admin. */
|
|
438
|
+
listDeliveries(p = {}) {
|
|
439
|
+
return this.h.request("GET", "/v1/webhook-deliveries", { params: p });
|
|
440
|
+
}
|
|
441
|
+
/** Deliver the event again with the same event id. Scope: webhook:admin. */
|
|
442
|
+
replayDelivery(deliveryId, o = {}) {
|
|
443
|
+
return this.h.request("POST", `/v1/webhook-deliveries/${deliveryId}/replay`, { json: {}, ...o });
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
var Events = class extends Resource {
|
|
447
|
+
/** Events for reconciliation, oldest first from the cursor. Scope: fax:read. */
|
|
448
|
+
list(p = {}) {
|
|
449
|
+
return this.h.request("GET", "/v1/events", { params: p });
|
|
450
|
+
}
|
|
451
|
+
/** Every event, following next_cursor. */
|
|
452
|
+
iter(p = {}) {
|
|
453
|
+
return paginate((cursor) => this.list({ ...p, cursor }));
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
var Billing = class extends Resource {
|
|
457
|
+
/** Available and held balance of this key's environment. Scope: billing:read. */
|
|
458
|
+
balance() {
|
|
459
|
+
return this.h.request("GET", "/v1/balance");
|
|
460
|
+
}
|
|
461
|
+
/** Wallet transactions, newest first. Scope: billing:read. */
|
|
462
|
+
listLedger(p = {}) {
|
|
463
|
+
return this.h.request("GET", "/v1/ledger", { params: p });
|
|
464
|
+
}
|
|
465
|
+
/** Billing settings of the organization. Scope: billing:read. */
|
|
466
|
+
getSettings() {
|
|
467
|
+
return this.h.request("GET", "/v1/billing-settings");
|
|
468
|
+
}
|
|
469
|
+
/** Change the billing email or the low-balance threshold. Scope: billing:write. */
|
|
470
|
+
patchSettings(body, o = {}) {
|
|
471
|
+
return this.h.request("PATCH", "/v1/billing-settings", { json: body, ...o });
|
|
472
|
+
}
|
|
473
|
+
/** A hosted Checkout to fund the live wallet. Scope: billing:write. */
|
|
474
|
+
createTopupSession(body, o = {}) {
|
|
475
|
+
return this.h.request("POST", "/v1/topup-sessions", { json: body, ...o });
|
|
476
|
+
}
|
|
477
|
+
/** Top-up sessions, newest first. Scope: billing:read. */
|
|
478
|
+
listTopupSessions(p = {}) {
|
|
479
|
+
return this.h.request("GET", "/v1/topup-sessions", { params: p });
|
|
480
|
+
}
|
|
481
|
+
/** Read a top-up session. Scope: billing:read. */
|
|
482
|
+
getTopupSession(topupSessionId) {
|
|
483
|
+
return this.h.request("GET", `/v1/topup-sessions/${topupSessionId}`);
|
|
484
|
+
}
|
|
485
|
+
/** Auto top-up settings. Scope: billing:read. */
|
|
486
|
+
listAutoTopups() {
|
|
487
|
+
return this.h.request("GET", "/v1/auto-topups");
|
|
488
|
+
}
|
|
489
|
+
/** Opt in to auto top-up. Scope: billing:write. */
|
|
490
|
+
createAutoTopup(body, o = {}) {
|
|
491
|
+
return this.h.request("POST", "/v1/auto-topups", { json: body, ...o });
|
|
492
|
+
}
|
|
493
|
+
/** Turn auto top-up off. Scope: billing:write. */
|
|
494
|
+
deleteAutoTopup(autoTopupId, o = {}) {
|
|
495
|
+
return this.h.request("DELETE", `/v1/auto-topups/${autoTopupId}`, o);
|
|
496
|
+
}
|
|
497
|
+
/** Spending caps of this environment. Scope: billing:read. */
|
|
498
|
+
listBudgets() {
|
|
499
|
+
return this.h.request("GET", "/v1/budgets");
|
|
500
|
+
}
|
|
501
|
+
/** A daily or monthly cap for the organization, a project or an agent. Scope: billing:write. */
|
|
502
|
+
createBudget(body, o = {}) {
|
|
503
|
+
return this.h.request("POST", "/v1/budgets", { json: body, ...o });
|
|
504
|
+
}
|
|
505
|
+
/** Change a cap's limit or status. Scope: billing:write. */
|
|
506
|
+
patchBudget(budgetId, body, o = {}) {
|
|
507
|
+
return this.h.request("PATCH", `/v1/budgets/${budgetId}`, { json: body, ...o });
|
|
508
|
+
}
|
|
509
|
+
/** Usage rollups by day, direction, destination and project. Scope: billing:read. */
|
|
510
|
+
usage(p = {}) {
|
|
511
|
+
return this.h.request("GET", "/v1/usage", { params: p });
|
|
512
|
+
}
|
|
513
|
+
/** Export usage as CSV behind a signed download. Scope: billing:read. */
|
|
514
|
+
createUsageExport(body, o = {}) {
|
|
515
|
+
return this.h.request("POST", "/v1/usage-exports", { json: body, ...o });
|
|
516
|
+
}
|
|
517
|
+
/** Read a usage export with a fresh link. Scope: billing:read. */
|
|
518
|
+
getUsageExport(exportId) {
|
|
519
|
+
return this.h.request("GET", `/v1/usage-exports/${exportId}`);
|
|
520
|
+
}
|
|
521
|
+
/** Stripe invoices and receipts as hosted links. Scope: billing:read. */
|
|
522
|
+
listInvoices(p = {}) {
|
|
523
|
+
return this.h.request("GET", "/v1/invoices", { params: p });
|
|
524
|
+
}
|
|
525
|
+
/** One invoice. Scope: billing:read. */
|
|
526
|
+
getInvoice(invoiceId) {
|
|
527
|
+
return this.h.request("GET", `/v1/invoices/${invoiceId}`);
|
|
528
|
+
}
|
|
529
|
+
/** A hosted Checkout for the Agent workspace subscription. Scope: billing:write. */
|
|
530
|
+
createSubscriptionCheckout(o = {}) {
|
|
531
|
+
return this.h.request("POST", "/v1/subscriptions/checkout", { json: {}, ...o });
|
|
532
|
+
}
|
|
533
|
+
/** Subscriptions and the workspace entitlement. Scope: billing:read. */
|
|
534
|
+
listSubscriptions() {
|
|
535
|
+
return this.h.request("GET", "/v1/subscriptions");
|
|
536
|
+
}
|
|
537
|
+
/** The Stripe customer portal. Scope: billing:write. */
|
|
538
|
+
createPortalSession(o = {}) {
|
|
539
|
+
return this.h.request("POST", "/v1/billing-portal-sessions", { json: {}, ...o });
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
var Platform = class extends Resource {
|
|
543
|
+
/** Limits, routes, formats, prices and scopes in force. Scope: any. */
|
|
544
|
+
capabilities() {
|
|
545
|
+
return this.h.request("GET", "/v1/capabilities");
|
|
546
|
+
}
|
|
547
|
+
/** Customer-safe availability. Scope: any. */
|
|
548
|
+
serviceStatus() {
|
|
549
|
+
return this.h.request("GET", "/v1/service-status");
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
var Sandbox = class extends Resource {
|
|
553
|
+
/** The scenario catalog, the destination table and active fixtures. Test keys only. */
|
|
554
|
+
listScenarios() {
|
|
555
|
+
return this.h.request("GET", "/v1/sandbox/scenarios");
|
|
556
|
+
}
|
|
557
|
+
/** Pin an outcome to a destination (or to every send) for 24 hours. Test keys only. */
|
|
558
|
+
createScenario(body, o = {}) {
|
|
559
|
+
return this.h.request("POST", "/v1/sandbox/scenarios", { json: body, ...o });
|
|
560
|
+
}
|
|
561
|
+
/** A synthetic received fax and its fax.received event. Test keys only. */
|
|
562
|
+
createInboundFax(body, o = {}) {
|
|
563
|
+
return this.h.request("POST", "/v1/sandbox/inbound-faxes", { json: body, ...o });
|
|
564
|
+
}
|
|
565
|
+
/** Delete the organization's test data and reseed the test wallet. Test keys only. */
|
|
566
|
+
reset(o = {}) {
|
|
567
|
+
return this.h.request("DELETE", "/v1/sandbox/data", o);
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
var Approvals = class extends Resource {
|
|
571
|
+
/** Ask a person to approve a quoted send. Grants nothing. Scope: approval:request. */
|
|
572
|
+
request(quoteId, o = {}) {
|
|
573
|
+
return this.h.request("POST", "/v1/approval-requests", { json: { kind: "send", quote_id: quoteId }, ...o });
|
|
574
|
+
}
|
|
575
|
+
/** Ask a person for help. The message is shown as data. Scope: approval:request. */
|
|
576
|
+
requestHelp(message, opts = {}) {
|
|
577
|
+
const { faxJobId, ...o } = opts;
|
|
578
|
+
return this.h.request("POST", "/v1/approval-requests", {
|
|
579
|
+
json: { kind: "help", message, fax_job_id: faxJobId },
|
|
580
|
+
...o
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
/** Requests, pending first. Scope: approval:read. */
|
|
584
|
+
list(p = {}) {
|
|
585
|
+
return this.h.request("GET", "/v1/approval-requests", { params: p });
|
|
586
|
+
}
|
|
587
|
+
/** Every request, following next_cursor. */
|
|
588
|
+
iter(p = {}) {
|
|
589
|
+
return paginate((cursor) => this.list({ ...p, cursor }));
|
|
590
|
+
}
|
|
591
|
+
/** One request. Scope: approval:read. */
|
|
592
|
+
get(approvalId) {
|
|
593
|
+
return this.h.request("GET", `/v1/approval-requests/${approvalId}`);
|
|
594
|
+
}
|
|
595
|
+
/** Poll until the request leaves pending, or the timeout passes. */
|
|
596
|
+
async wait(approvalId, opts = {}) {
|
|
597
|
+
const deadline = Date.now() + (opts.timeoutMs ?? 6e5);
|
|
598
|
+
let req = await this.get(approvalId);
|
|
599
|
+
while (req.status === "pending" && Date.now() < deadline) {
|
|
600
|
+
await sleep2(opts.intervalMs ?? 5e3);
|
|
601
|
+
req = await this.get(approvalId);
|
|
602
|
+
}
|
|
603
|
+
return req;
|
|
604
|
+
}
|
|
605
|
+
/** Approve the bound send. Scope: approval:decide, never the key that asked, never an agent key. */
|
|
606
|
+
approve(approvalId, body = {}, o = {}) {
|
|
607
|
+
return this.h.request("POST", `/v1/approval-requests/${approvalId}/approve`, { json: body, ...o });
|
|
608
|
+
}
|
|
609
|
+
/** Reject with a reason. Scope: approval:decide. */
|
|
610
|
+
reject(approvalId, body, o = {}) {
|
|
611
|
+
return this.h.request("POST", `/v1/approval-requests/${approvalId}/reject`, { json: body, ...o });
|
|
612
|
+
}
|
|
613
|
+
/** Revoke an approval nobody has used yet. Scope: approval:decide. */
|
|
614
|
+
revoke(approvalId, body = {}, o = {}) {
|
|
615
|
+
return this.h.request("POST", `/v1/approvals/${approvalId}/revoke`, { json: body, ...o });
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
var Policies = class extends Resource {
|
|
619
|
+
/** The organization's policies. Scope: policy:read. */
|
|
620
|
+
list() {
|
|
621
|
+
return this.h.request("GET", "/v1/policies");
|
|
622
|
+
}
|
|
623
|
+
/** Create a delegated policy, version 1. Scope: policy:admin, never an agent key. */
|
|
624
|
+
create(body, o = {}) {
|
|
625
|
+
return this.h.request("POST", "/v1/policies", { json: body, ...o });
|
|
626
|
+
}
|
|
627
|
+
/** What this key is allowed to do alone, and whether a human is needed. Scope: policy:read. */
|
|
628
|
+
effective() {
|
|
629
|
+
return this.h.request("GET", "/v1/policies/effective");
|
|
630
|
+
}
|
|
631
|
+
/** A policy at its current version. Scope: policy:read. */
|
|
632
|
+
get(policyId) {
|
|
633
|
+
return this.h.request("GET", `/v1/policies/${policyId}`);
|
|
634
|
+
}
|
|
635
|
+
/** Change a policy: a new immutable version. Scope: policy:admin. */
|
|
636
|
+
update(policyId, body, o = {}) {
|
|
637
|
+
return this.h.request("PATCH", `/v1/policies/${policyId}`, { json: body, ...o });
|
|
638
|
+
}
|
|
639
|
+
/** Every version, oldest first. Scope: policy:read. */
|
|
640
|
+
listVersions(policyId) {
|
|
641
|
+
return this.h.request("GET", `/v1/policies/${policyId}/versions`);
|
|
642
|
+
}
|
|
643
|
+
/** Dry run: would this key's policies allow the send? Never executes. Scope: policy:read. */
|
|
644
|
+
evaluate(body) {
|
|
645
|
+
return this.h.request("POST", "/v1/policy-evaluations", { json: body });
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
var Agents = class extends Resource {
|
|
649
|
+
/** Agent identities. Scope: agent:read. */
|
|
650
|
+
list() {
|
|
651
|
+
return this.h.request("GET", "/v1/agents");
|
|
652
|
+
}
|
|
653
|
+
/** Register an agent identity. Scope: agent:admin, never an agent key. */
|
|
654
|
+
create(body, o = {}) {
|
|
655
|
+
return this.h.request("POST", "/v1/agents", { json: body, ...o });
|
|
656
|
+
}
|
|
657
|
+
/** An agent with its keys and budgets. Scope: agent:read. */
|
|
658
|
+
get(agentId) {
|
|
659
|
+
return this.h.request("GET", `/v1/agents/${agentId}`);
|
|
660
|
+
}
|
|
661
|
+
/** Change an agent. Disabling revokes its keys. Scope: agent:admin. */
|
|
662
|
+
update(agentId, body, o = {}) {
|
|
663
|
+
return this.h.request("PATCH", `/v1/agents/${agentId}`, { json: body, ...o });
|
|
664
|
+
}
|
|
665
|
+
/** Mint a key for the agent, bounded scopes, secret shown once. Scope: agent:admin and key:admin. */
|
|
666
|
+
createKey(agentId, body, o = {}) {
|
|
667
|
+
return this.h.request("POST", `/v1/agents/${agentId}/keys`, { json: body, ...o });
|
|
668
|
+
}
|
|
669
|
+
/** The agent's audit trail, metadata only. Scope: agent:read. */
|
|
670
|
+
activity(agentId, p = {}) {
|
|
671
|
+
return this.h.request("GET", `/v1/agents/${agentId}/activity`, { params: p });
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
var Inbox = class extends Resource {
|
|
675
|
+
/** Received faxes, newest first, metadata only. `from` is sender data. Scope: inbox:read. */
|
|
676
|
+
list(p = {}) {
|
|
677
|
+
return this.h.request("GET", "/v1/inbox", { params: p });
|
|
678
|
+
}
|
|
679
|
+
/** Every received fax, following next_cursor. */
|
|
680
|
+
iter(p = {}) {
|
|
681
|
+
return paginate((cursor) => this.list({ ...p, cursor }));
|
|
682
|
+
}
|
|
683
|
+
/** One received fax with its text as data, never as instructions. Scope: inbox:read. */
|
|
684
|
+
get(inboxId) {
|
|
685
|
+
return this.h.request("GET", `/v1/inbox/${inboxId}`);
|
|
686
|
+
}
|
|
687
|
+
/** Mark a received fax read or archived, or received again. Scope: inbox:write. */
|
|
688
|
+
update(inboxId, body, o = {}) {
|
|
689
|
+
return this.h.request("PATCH", `/v1/inbox/${inboxId}`, { json: body, ...o });
|
|
690
|
+
}
|
|
691
|
+
/** Delete a received fax. Scope: inbox:write. */
|
|
692
|
+
delete(inboxId, o = {}) {
|
|
693
|
+
return this.h.request("DELETE", `/v1/inbox/${inboxId}`, o);
|
|
694
|
+
}
|
|
695
|
+
/** A signed link to the received PDF, valid ten minutes. Scope: inbox:read. */
|
|
696
|
+
getDownload(inboxId) {
|
|
697
|
+
return this.h.request("GET", `/v1/inbox/${inboxId}/download`);
|
|
698
|
+
}
|
|
699
|
+
/** The received PDF bytes, through a fresh signed URL. */
|
|
700
|
+
async download(inboxId) {
|
|
701
|
+
const link = await this.getDownload(inboxId);
|
|
702
|
+
return this.h.bytes("GET", link.url);
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
var Numbers = class extends Resource {
|
|
706
|
+
/** Where faxes are sent and where numbers are hosted. Scope: number:read. */
|
|
707
|
+
coverage() {
|
|
708
|
+
return this.h.request("GET", "/v1/coverage");
|
|
709
|
+
}
|
|
710
|
+
/** Fax-capable numbers for sale. Scope: number:read. */
|
|
711
|
+
inventory(p = {}) {
|
|
712
|
+
return this.h.request("GET", "/v1/number-inventory", { params: p });
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Buy a number from the inventory. The first month is held now and charged on activation.
|
|
716
|
+
* Scope: number:buy, never an agent key.
|
|
717
|
+
*/
|
|
718
|
+
createOrder(body, o = {}) {
|
|
719
|
+
return this.h.request("POST", "/v1/number-orders", { json: body, ...o });
|
|
720
|
+
}
|
|
721
|
+
/** Read a number order. Scope: number:read. */
|
|
722
|
+
getOrder(orderId) {
|
|
723
|
+
return this.h.request("GET", `/v1/number-orders/${orderId}`);
|
|
724
|
+
}
|
|
725
|
+
/** Your numbers. Scope: number:read. */
|
|
726
|
+
list(p = {}) {
|
|
727
|
+
return this.h.request("GET", "/v1/numbers", { params: p });
|
|
728
|
+
}
|
|
729
|
+
/** One number. Scope: number:read. */
|
|
730
|
+
get(numberId) {
|
|
731
|
+
return this.h.request("GET", `/v1/numbers/${numberId}`);
|
|
732
|
+
}
|
|
733
|
+
/** Change the label, project or inbound webhook of a number. Scope: number:buy. */
|
|
734
|
+
update(numberId, body, o = {}) {
|
|
735
|
+
return this.h.request("PATCH", `/v1/numbers/${numberId}`, { json: body, ...o });
|
|
736
|
+
}
|
|
737
|
+
/** Release a number. `confirm` is the number itself, typed out. A 30 day quarantine follows. Scope: number:buy. */
|
|
738
|
+
release(numberId, body, o = {}) {
|
|
739
|
+
return this.h.request("POST", `/v1/numbers/${numberId}/release-requests`, { json: body, ...o });
|
|
740
|
+
}
|
|
741
|
+
/** Whether these numbers can port in. Scope: number:read. */
|
|
742
|
+
checkPortability(body, o = {}) {
|
|
743
|
+
return this.h.request("POST", "/v1/portability-checks", { json: body, ...o });
|
|
744
|
+
}
|
|
745
|
+
/** Port orders and port-out requests. Scope: number:read. */
|
|
746
|
+
listPortOrders() {
|
|
747
|
+
return this.h.request("GET", "/v1/port-orders");
|
|
748
|
+
}
|
|
749
|
+
/** Request a port-in, handled with you. Scope: number:buy. */
|
|
750
|
+
createPortOrder(body, o = {}) {
|
|
751
|
+
return this.h.request("POST", "/v1/port-orders", { json: body, ...o });
|
|
752
|
+
}
|
|
753
|
+
/** One port order. Scope: number:read. */
|
|
754
|
+
getPortOrder(portId) {
|
|
755
|
+
return this.h.request("GET", `/v1/port-orders/${portId}`);
|
|
756
|
+
}
|
|
757
|
+
/** Note a port-out of one of your numbers. Scope: number:buy. */
|
|
758
|
+
createPortOutRequest(body, o = {}) {
|
|
759
|
+
return this.h.request("POST", "/v1/port-out-requests", { json: body, ...o });
|
|
760
|
+
}
|
|
761
|
+
/** Verify a number your organization owns as a sender. Scope: number:buy. */
|
|
762
|
+
verifySender(body, o = {}) {
|
|
763
|
+
return this.h.request("POST", "/v1/sender-verifications", { json: body, ...o });
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
var Extractions = class extends Resource {
|
|
767
|
+
/**
|
|
768
|
+
* OCR a received fax or a document, then extract the schema's fields with page citations. Metered per
|
|
769
|
+
* page. Everything it returns is data from whoever sent the fax. Scope: document:extract.
|
|
770
|
+
*/
|
|
771
|
+
create(body, o = {}) {
|
|
772
|
+
return this.h.request("POST", "/v1/extractions", { json: body, ...o });
|
|
773
|
+
}
|
|
774
|
+
/** Extractions, newest first. Scope: document:extract. */
|
|
775
|
+
list(p = {}) {
|
|
776
|
+
return this.h.request("GET", "/v1/extractions", { params: p });
|
|
777
|
+
}
|
|
778
|
+
/** Every extraction, following next_cursor. */
|
|
779
|
+
iter(p = {}) {
|
|
780
|
+
return paginate((cursor) => this.list({ ...p, cursor }));
|
|
781
|
+
}
|
|
782
|
+
/** One extraction with its corrections. Scope: document:extract. */
|
|
783
|
+
get(extractionId) {
|
|
784
|
+
return this.h.request("GET", `/v1/extractions/${extractionId}`);
|
|
785
|
+
}
|
|
786
|
+
/** Record a reviewer's correction of one field. Stored beside the extraction, never merged. Scope: document:extract. */
|
|
787
|
+
correct(extractionId, body, o = {}) {
|
|
788
|
+
return this.h.request("POST", `/v1/extractions/${extractionId}/corrections`, { json: body, ...o });
|
|
789
|
+
}
|
|
790
|
+
/** Classify a received fax or a document into one of your document types, or abstain. Scope: document:extract. */
|
|
791
|
+
classify(body, o = {}) {
|
|
792
|
+
return this.h.request("POST", "/v1/classifications", { json: body, ...o });
|
|
793
|
+
}
|
|
794
|
+
/** Classifications, newest first. Scope: document:extract. */
|
|
795
|
+
listClassifications(p = {}) {
|
|
796
|
+
return this.h.request("GET", "/v1/classifications", { params: p });
|
|
797
|
+
}
|
|
798
|
+
/** Every classification, following next_cursor. */
|
|
799
|
+
iterClassifications(p = {}) {
|
|
800
|
+
return paginate((cursor) => this.listClassifications({ ...p, cursor }));
|
|
801
|
+
}
|
|
802
|
+
/** One classification. Scope: document:extract. */
|
|
803
|
+
getClassification(classificationId) {
|
|
804
|
+
return this.h.request("GET", `/v1/classifications/${classificationId}`);
|
|
805
|
+
}
|
|
806
|
+
/** Summarise a received fax or a document. Every sentence cites its pages. Scope: document:extract. */
|
|
807
|
+
summarize(body, o = {}) {
|
|
808
|
+
return this.h.request("POST", "/v1/document-summaries", { json: body, ...o });
|
|
809
|
+
}
|
|
810
|
+
/** Summaries, newest first. Scope: document:extract. */
|
|
811
|
+
listSummaries(p = {}) {
|
|
812
|
+
return this.h.request("GET", "/v1/document-summaries", { params: p });
|
|
813
|
+
}
|
|
814
|
+
/** Every summary, following next_cursor. */
|
|
815
|
+
iterSummaries(p = {}) {
|
|
816
|
+
return paginate((cursor) => this.listSummaries({ ...p, cursor }));
|
|
817
|
+
}
|
|
818
|
+
/** One summary. Scope: document:extract. */
|
|
819
|
+
getSummary(summaryId) {
|
|
820
|
+
return this.h.request("GET", `/v1/document-summaries/${summaryId}`);
|
|
821
|
+
}
|
|
822
|
+
/** Your saved extraction schemas. Scope: document:extract. */
|
|
823
|
+
listSchemas() {
|
|
824
|
+
return this.h.request("GET", "/v1/extraction-schemas");
|
|
825
|
+
}
|
|
826
|
+
/** Save a versioned extraction schema. The same name again is the next version. Scope: document:extract. */
|
|
827
|
+
createSchema(body, o = {}) {
|
|
828
|
+
return this.h.request("POST", "/v1/extraction-schemas", { json: body, ...o });
|
|
829
|
+
}
|
|
830
|
+
/** One schema version. Scope: document:extract. */
|
|
831
|
+
getSchema(schemaId) {
|
|
832
|
+
return this.h.request("GET", `/v1/extraction-schemas/${schemaId}`);
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
var Organizations = class extends Resource {
|
|
836
|
+
/** The organizations the caller belongs to. Scope: any. */
|
|
837
|
+
list() {
|
|
838
|
+
return this.h.request("GET", "/v1/organizations");
|
|
839
|
+
}
|
|
840
|
+
/** The organization of this key. Scope: account:read. */
|
|
841
|
+
current() {
|
|
842
|
+
return this.h.request("GET", "/v1/organizations/current");
|
|
843
|
+
}
|
|
844
|
+
/** Rename the organization. Scope: member:admin, never an agent key. */
|
|
845
|
+
updateCurrent(body, o = {}) {
|
|
846
|
+
return this.h.request("PATCH", "/v1/organizations/current", { json: body, ...o });
|
|
847
|
+
}
|
|
848
|
+
/** Ask for an export of the organization's data. Scope: org:admin, never an agent key. */
|
|
849
|
+
requestDataExport(o = {}) {
|
|
850
|
+
return this.h.request("POST", "/v1/organizations/current/export-requests", { json: {}, ...o });
|
|
851
|
+
}
|
|
852
|
+
/** Ask for the organization and its data to be deleted. Scope: org:admin, never an agent key. */
|
|
853
|
+
requestDataDeletion(o = {}) {
|
|
854
|
+
return this.h.request("POST", "/v1/organizations/current/deletion-requests", { json: {}, ...o });
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
var Members = class extends Resource {
|
|
858
|
+
/** The organization's members. Scope: account:read. */
|
|
859
|
+
list() {
|
|
860
|
+
return this.h.request("GET", "/v1/members");
|
|
861
|
+
}
|
|
862
|
+
/** Change a member's role: owner, admin, member or viewer. Scope: member:admin, never an agent key. */
|
|
863
|
+
update(memberId, body, o = {}) {
|
|
864
|
+
return this.h.request("PATCH", `/v1/members/${memberId}`, { json: body, ...o });
|
|
865
|
+
}
|
|
866
|
+
/** Remove a member. Scope: org:admin, never an agent key. */
|
|
867
|
+
async remove(memberId, o = {}) {
|
|
868
|
+
await this.h.request("DELETE", `/v1/members/${memberId}`, o);
|
|
869
|
+
}
|
|
870
|
+
/** Open invitations. Scope: member:admin. */
|
|
871
|
+
listInvitations() {
|
|
872
|
+
return this.h.request("GET", "/v1/invitations");
|
|
873
|
+
}
|
|
874
|
+
/** Invite someone by email, a link that works for 7 days. Scope: member:admin, never an agent key. */
|
|
875
|
+
invite(body, o = {}) {
|
|
876
|
+
return this.h.request("POST", "/v1/invitations", { json: body, ...o });
|
|
877
|
+
}
|
|
878
|
+
/** Withdraw an invitation. Scope: member:admin, never an agent key. */
|
|
879
|
+
async revokeInvitation(invitationId, o = {}) {
|
|
880
|
+
await this.h.request("DELETE", `/v1/invitations/${invitationId}`, o);
|
|
881
|
+
}
|
|
882
|
+
};
|
|
883
|
+
var FaxForAgents = class {
|
|
884
|
+
http;
|
|
885
|
+
identity;
|
|
886
|
+
documents;
|
|
887
|
+
quotes;
|
|
888
|
+
faxes;
|
|
889
|
+
webhooks;
|
|
890
|
+
events;
|
|
891
|
+
billing;
|
|
892
|
+
platform;
|
|
893
|
+
sandbox;
|
|
894
|
+
approvals;
|
|
895
|
+
policies;
|
|
896
|
+
agents;
|
|
897
|
+
inbox;
|
|
898
|
+
numbers;
|
|
899
|
+
extractions;
|
|
900
|
+
organizations;
|
|
901
|
+
members;
|
|
902
|
+
constructor(opts = {}) {
|
|
903
|
+
this.http = new Http(opts);
|
|
904
|
+
this.identity = new Identity(this.http);
|
|
905
|
+
this.documents = new Documents(this.http);
|
|
906
|
+
this.quotes = new Quotes(this.http);
|
|
907
|
+
this.faxes = new Faxes(this.http);
|
|
908
|
+
this.webhooks = new Webhooks(this.http);
|
|
909
|
+
this.events = new Events(this.http);
|
|
910
|
+
this.billing = new Billing(this.http);
|
|
911
|
+
this.platform = new Platform(this.http);
|
|
912
|
+
this.sandbox = new Sandbox(this.http);
|
|
913
|
+
this.approvals = new Approvals(this.http);
|
|
914
|
+
this.policies = new Policies(this.http);
|
|
915
|
+
this.agents = new Agents(this.http);
|
|
916
|
+
this.inbox = new Inbox(this.http);
|
|
917
|
+
this.numbers = new Numbers(this.http);
|
|
918
|
+
this.extractions = new Extractions(this.http);
|
|
919
|
+
this.organizations = new Organizations(this.http);
|
|
920
|
+
this.members = new Members(this.http);
|
|
921
|
+
}
|
|
922
|
+
/** Shortcut for identity.me(). */
|
|
923
|
+
me() {
|
|
924
|
+
return this.identity.me();
|
|
925
|
+
}
|
|
926
|
+
/** Any operation the resources do not cover yet. Returns the parsed JSON. */
|
|
927
|
+
request(method, path, opts = {}) {
|
|
928
|
+
return this.http.request(method, path, opts);
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
|
|
932
|
+
// src/webhooks.ts
|
|
933
|
+
var SECRET_PREFIX = "whsec_";
|
|
934
|
+
var TOLERANCE_S = 300;
|
|
935
|
+
var SignatureError = class extends Error {
|
|
936
|
+
constructor(message) {
|
|
937
|
+
super(message);
|
|
938
|
+
this.name = "SignatureError";
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
var enc = new TextEncoder();
|
|
942
|
+
function b64encode(bytes) {
|
|
943
|
+
let s = "";
|
|
944
|
+
for (const b of bytes) s += String.fromCharCode(b);
|
|
945
|
+
return btoa(s);
|
|
946
|
+
}
|
|
947
|
+
function b64decode(text) {
|
|
948
|
+
const s = atob(text);
|
|
949
|
+
const out = new Uint8Array(s.length);
|
|
950
|
+
for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
|
|
951
|
+
return out;
|
|
952
|
+
}
|
|
953
|
+
function keyBytes(secret) {
|
|
954
|
+
const raw = secret.startsWith(SECRET_PREFIX) ? secret.slice(SECRET_PREFIX.length) : secret;
|
|
955
|
+
return b64decode(raw);
|
|
956
|
+
}
|
|
957
|
+
function toBytes(body) {
|
|
958
|
+
if (typeof body === "string") return enc.encode(body);
|
|
959
|
+
if (body instanceof ArrayBuffer) return new Uint8Array(body);
|
|
960
|
+
return new Uint8Array(body);
|
|
961
|
+
}
|
|
962
|
+
function headerLookup(headers) {
|
|
963
|
+
if (typeof headers.get === "function") {
|
|
964
|
+
const h = headers;
|
|
965
|
+
return (name) => h.get(name) ?? "";
|
|
966
|
+
}
|
|
967
|
+
const map = /* @__PURE__ */ new Map();
|
|
968
|
+
const entries = typeof headers[Symbol.iterator] === "function" ? headers : Object.entries(headers);
|
|
969
|
+
for (const [k, v] of entries) {
|
|
970
|
+
const value = Array.isArray(v) ? v.join(" ") : v;
|
|
971
|
+
if (typeof value === "string") map.set(k.toLowerCase(), value);
|
|
972
|
+
}
|
|
973
|
+
return (name) => map.get(name) ?? "";
|
|
974
|
+
}
|
|
975
|
+
function timingSafeEqual(a, b) {
|
|
976
|
+
const x = enc.encode(a);
|
|
977
|
+
const y = enc.encode(b);
|
|
978
|
+
if (x.length !== y.length) return false;
|
|
979
|
+
let diff = 0;
|
|
980
|
+
for (let i = 0; i < x.length; i++) diff |= x[i] ^ y[i];
|
|
981
|
+
return diff === 0;
|
|
982
|
+
}
|
|
983
|
+
async function sign(secret, msgId, timestamp, body) {
|
|
984
|
+
const key = await crypto.subtle.importKey("raw", keyBytes(secret), { name: "HMAC", hash: "SHA-256" }, false, [
|
|
985
|
+
"sign"
|
|
986
|
+
]);
|
|
987
|
+
const prefix = enc.encode(`${msgId}.${timestamp}.`);
|
|
988
|
+
const payload = toBytes(body);
|
|
989
|
+
const toSign = new Uint8Array(prefix.length + payload.length);
|
|
990
|
+
toSign.set(prefix, 0);
|
|
991
|
+
toSign.set(payload, prefix.length);
|
|
992
|
+
const digest = await crypto.subtle.sign("HMAC", key, toSign);
|
|
993
|
+
return "v1," + b64encode(new Uint8Array(digest));
|
|
994
|
+
}
|
|
995
|
+
async function signatureHeaders(secrets, msgId, body, timestamp = Math.floor(Date.now() / 1e3)) {
|
|
996
|
+
const sigs = await Promise.all(secrets.map((s) => sign(s, msgId, timestamp, body)));
|
|
997
|
+
return {
|
|
998
|
+
"webhook-id": msgId,
|
|
999
|
+
"webhook-timestamp": String(timestamp),
|
|
1000
|
+
"webhook-signature": sigs.join(" "),
|
|
1001
|
+
"content-type": "application/json"
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
async function verifyWebhook(secret, headers, body, opts = {}) {
|
|
1005
|
+
const get = headerLookup(headers);
|
|
1006
|
+
const msgId = get("webhook-id");
|
|
1007
|
+
const tsRaw = get("webhook-timestamp");
|
|
1008
|
+
const sigs = get("webhook-signature");
|
|
1009
|
+
if (!msgId || !tsRaw || !sigs) throw new SignatureError("missing webhook headers");
|
|
1010
|
+
if (!/^\d+$/.test(tsRaw.trim())) throw new SignatureError("bad timestamp");
|
|
1011
|
+
const ts = Number(tsRaw);
|
|
1012
|
+
const now = opts.now ?? Date.now() / 1e3;
|
|
1013
|
+
if (Math.abs(now - ts) > (opts.toleranceS ?? TOLERANCE_S)) throw new SignatureError("timestamp outside tolerance");
|
|
1014
|
+
const expected = await sign(secret, msgId, ts, body);
|
|
1015
|
+
for (const candidate of sigs.split(/\s+/)) {
|
|
1016
|
+
if (candidate.startsWith("v1,") && timingSafeEqual(candidate, expected)) return msgId;
|
|
1017
|
+
}
|
|
1018
|
+
throw new SignatureError("no matching signature");
|
|
1019
|
+
}
|
|
1020
|
+
function parseEvent(body) {
|
|
1021
|
+
const text = typeof body === "string" ? body : new TextDecoder().decode(toBytes(body));
|
|
1022
|
+
return JSON.parse(text);
|
|
1023
|
+
}
|
|
1024
|
+
export {
|
|
1025
|
+
APIConnectionError,
|
|
1026
|
+
APIError,
|
|
1027
|
+
APITimeoutError,
|
|
1028
|
+
Agents,
|
|
1029
|
+
Approvals,
|
|
1030
|
+
AuthenticationError,
|
|
1031
|
+
Billing,
|
|
1032
|
+
CONTENT_TYPES,
|
|
1033
|
+
FaxForAgents as Client,
|
|
1034
|
+
ConflictError,
|
|
1035
|
+
DEFAULT_BASE_URL,
|
|
1036
|
+
Documents,
|
|
1037
|
+
Events,
|
|
1038
|
+
Extractions,
|
|
1039
|
+
FaxForAgents,
|
|
1040
|
+
FaxForAgentsError,
|
|
1041
|
+
Faxes,
|
|
1042
|
+
Http,
|
|
1043
|
+
Identity,
|
|
1044
|
+
Inbox,
|
|
1045
|
+
InvalidRequestError,
|
|
1046
|
+
Members,
|
|
1047
|
+
NotFoundError,
|
|
1048
|
+
Numbers,
|
|
1049
|
+
Organizations,
|
|
1050
|
+
PaymentRequiredError,
|
|
1051
|
+
Platform,
|
|
1052
|
+
Policies,
|
|
1053
|
+
Quotes,
|
|
1054
|
+
RateLimitedError,
|
|
1055
|
+
Sandbox,
|
|
1056
|
+
ScopeError,
|
|
1057
|
+
ServerError,
|
|
1058
|
+
SignatureError,
|
|
1059
|
+
TERMINAL_STATES,
|
|
1060
|
+
VERSION,
|
|
1061
|
+
Webhooks,
|
|
1062
|
+
guessContentType,
|
|
1063
|
+
paginate,
|
|
1064
|
+
parseEvent,
|
|
1065
|
+
sign,
|
|
1066
|
+
signatureHeaders,
|
|
1067
|
+
verifyWebhook
|
|
1068
|
+
};
|
|
1069
|
+
//# sourceMappingURL=index.js.map
|