@a3api/node 0.1.0 → 0.1.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/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # @a3api/node
2
+
3
+ Official Node.js client for the [Arcadia Age API (A3)](https://www.a3api.io). Handles request construction, typed responses, automatic retries, and structured error handling.
4
+
5
+ - Full TypeScript types for requests and responses
6
+ - Automatic retry with exponential backoff (429, 5xx, network errors)
7
+ - Typed error classes for each failure mode
8
+ - ESM + CJS + type declarations
9
+ - Zero dependencies (uses native `fetch`)
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install @a3api/node
15
+ ```
16
+
17
+ Requires Node.js 18 or later.
18
+
19
+ ## Quick Start
20
+
21
+ ```typescript
22
+ import { A3Client } from '@a3api/node';
23
+
24
+ const client = new A3Client({ apiKey: process.env.A3_API_KEY! });
25
+
26
+ const result = await client.assessAge({
27
+ os_signal: 'not-available',
28
+ user_country_code: 'US',
29
+ behavioral_metrics: {
30
+ avg_touch_precision: 0.72,
31
+ scroll_velocity: 1200,
32
+ form_completion_time_ms: 8500,
33
+ },
34
+ });
35
+
36
+ console.log(result.verdict); // "PROVISIONAL"
37
+ console.log(result.assessed_age_bracket); // "18-plus"
38
+ console.log(result.confidence_score); // 0.7
39
+ ```
40
+
41
+ ## Constructor Options
42
+
43
+ ```typescript
44
+ const client = new A3Client({
45
+ apiKey: 'your_api_key', // Required
46
+ baseUrl: 'https://...', // Default: https://api.a3api.io
47
+ timeout: 30_000, // Default: 30000 (ms)
48
+ maxRetries: 2, // Default: 2
49
+ });
50
+ ```
51
+
52
+ | Option | Type | Default | Description |
53
+ |--------|------|---------|-------------|
54
+ | `apiKey` | `string` | *required* | Your A3 API key |
55
+ | `baseUrl` | `string` | `https://api.a3api.io` | API base URL |
56
+ | `timeout` | `number` | `30000` | Request timeout in milliseconds |
57
+ | `maxRetries` | `number` | `2` | Max retries for transient failures |
58
+
59
+ ## `client.assessAge(request)`
60
+
61
+ Sends signals to `POST /v1/assurance/assess-age` and returns the assessment.
62
+
63
+ ### Request
64
+
65
+ | Field | Type | Required | Description |
66
+ |-------|------|----------|-------------|
67
+ | `os_signal` | `OsSignal` | Yes | `'under-13'` \| `'13-15'` \| `'16-17'` \| `'18-plus'` \| `'not-available'` |
68
+ | `user_country_code` | `string` | Yes | ISO 3166-1 alpha-2 code (e.g., `'US'`) |
69
+ | `behavioral_metrics` | `BehavioralMetrics` | No | Touch precision, scroll velocity, form timing, etc. |
70
+ | `device_context` | `DeviceContext` | No | OS version, device model, accessibility settings |
71
+ | `contextual_signals` | `ContextualSignals` | No | IP type, timezone offset, referrer category |
72
+ | `account_longevity` | `AccountLongevity` | No | `{ account_age_days: number }` |
73
+ | `input_complexity` | `InputComplexity` | No | Autocorrect rate, word complexity score |
74
+
75
+ ### Response
76
+
77
+ | Field | Type | Description |
78
+ |-------|------|-------------|
79
+ | `verdict` | `Verdict` | `'CONSISTENT'` \| `'OVERRIDE'` \| `'REVIEW'` \| `'PROVISIONAL'` |
80
+ | `assessed_age_bracket` | `AgeBracket` | `'under-13'` \| `'13-15'` \| `'16-17'` \| `'18-plus'` \| `'undetermined'` |
81
+ | `confidence_score` | `number` | 0–1 certainty in the assessed bracket (Pro/Scale plans only) |
82
+ | `os_signal_age_bracket` | `AgeBracket` | OS signal echoed back |
83
+ | `signal_overridden` | `boolean` | `true` when verdict is `OVERRIDE` |
84
+ | `evidence_tags` | `string[]` | Audit trail of which signals influenced the verdict (Pro/Scale plans only) |
85
+ | `verification_token` | `string` | HMAC-SHA256 signed cryptographic receipt — store in your logs |
86
+
87
+ ## Error Handling
88
+
89
+ The client throws typed errors you can catch individually:
90
+
91
+ ```typescript
92
+ import {
93
+ A3Client,
94
+ A3ValidationError,
95
+ A3AuthenticationError,
96
+ A3RateLimitError,
97
+ A3ConnectionError,
98
+ } from '@a3api/node';
99
+
100
+ try {
101
+ const result = await client.assessAge(request);
102
+ } catch (err) {
103
+ if (err instanceof A3ValidationError) {
104
+ // 400 — bad request body
105
+ console.error(err.validationErrors); // string[]
106
+ } else if (err instanceof A3AuthenticationError) {
107
+ // 401 — invalid API key
108
+ } else if (err instanceof A3RateLimitError) {
109
+ // 429 — rate limited (auto-retried, this means retries exhausted)
110
+ console.error(err.retryAfter); // ms until retry, if provided
111
+ } else if (err instanceof A3ConnectionError) {
112
+ // Network failure or timeout (auto-retried, retries exhausted)
113
+ }
114
+ }
115
+ ```
116
+
117
+ | Error Class | Status | Auto-Retried | Description |
118
+ |-------------|--------|:------------:|-------------|
119
+ | `A3ValidationError` | 400 | No | Request body failed validation |
120
+ | `A3AuthenticationError` | 401 | No | Missing or invalid API key |
121
+ | `A3RateLimitError` | 429 | Yes | Rate limit or quota exceeded |
122
+ | `A3ApiError` | 5xx | Yes | Server error |
123
+ | `A3ConnectionError` | — | Yes | Network failure or timeout |
124
+
125
+ ## Usage with Express
126
+
127
+ ```typescript
128
+ import express from 'express';
129
+ import { A3Client } from '@a3api/node';
130
+
131
+ const app = express();
132
+ app.use(express.json());
133
+
134
+ const a3 = new A3Client({ apiKey: process.env.A3_API_KEY! });
135
+
136
+ app.post('/api/assess-age', async (req, res) => {
137
+ const result = await a3.assessAge({
138
+ os_signal: 'not-available',
139
+ user_country_code: 'US',
140
+ ...req.body, // signals from @a3api/signals browser SDK
141
+ });
142
+
143
+ res.json({
144
+ verdict: result.verdict,
145
+ bracket: result.assessed_age_bracket,
146
+ });
147
+ });
148
+ ```
149
+
150
+ ## Links
151
+
152
+ - [Documentation](https://www.a3api.io/docs)
153
+ - [Web Integration Guide](https://www.a3api.io/docs/integration/web-integration)
154
+ - [API Reference](https://www.a3api.io/docs/integration/assess-age)
155
+ - [Quickstart Project](https://github.com/a3api/a3-quickstart)
156
+ - [Get an API Key](https://portal.a3api.io)
157
+
158
+ ## License
159
+
160
+ MIT
package/dist/index.cjs CHANGED
@@ -121,7 +121,7 @@ async function withRetry(fn, opts) {
121
121
  }
122
122
 
123
123
  // src/version.ts
124
- var SDK_VERSION = "0.1.0";
124
+ var SDK_VERSION = "0.1.2";
125
125
 
126
126
  // src/client.ts
127
127
  var DEFAULT_BASE_URL = "https://api.a3api.io";
@@ -166,7 +166,7 @@ var A3Client = class {
166
166
  method: "POST",
167
167
  headers: {
168
168
  "Content-Type": "application/json",
169
- "x-api-key": this.apiKey,
169
+ Authorization: `Bearer ${this.apiKey}`,
170
170
  "User-Agent": `a3api-node/${SDK_VERSION}`
171
171
  },
172
172
  body: JSON.stringify(request),
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/retry.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export { A3Client } from './client.js';\r\n\r\nexport type {\r\n A3ClientOptions,\r\n A3ErrorBody,\r\n AssessAgeRequest,\r\n AssessAgeResponse,\r\n OsSignal,\r\n Verdict,\r\n AgeBracket,\r\n ParentalConsentStatus,\r\n ConsentSource,\r\n FaceEstimationProvider,\r\n IpType,\r\n ReferrerCategory,\r\n BehavioralMetrics,\r\n DeviceContext,\r\n ContextualSignals,\r\n AccountLongevity,\r\n InputComplexity,\r\n FaceEstimationResult,\r\n} from './types.js';\r\n\r\nexport {\r\n A3ApiError,\r\n A3AuthenticationError,\r\n A3RateLimitError,\r\n A3ValidationError,\r\n A3ConnectionError,\r\n} from './errors.js';\r\n\r\nexport { SDK_VERSION } from './version.js';\r\n","import type { A3ErrorBody } from './types.js';\r\n\r\nexport class A3ApiError extends Error {\r\n readonly statusCode: number;\r\n readonly body: A3ErrorBody | undefined;\r\n\r\n constructor(message: string, statusCode: number, body?: A3ErrorBody) {\r\n super(message);\r\n this.name = 'A3ApiError';\r\n this.statusCode = statusCode;\r\n this.body = body;\r\n }\r\n}\r\n\r\nexport class A3AuthenticationError extends A3ApiError {\r\n constructor(body?: A3ErrorBody) {\r\n super(\r\n body?.message\r\n ? (Array.isArray(body.message) ? body.message.join(', ') : body.message)\r\n : 'Unauthorized',\r\n 401,\r\n body,\r\n );\r\n this.name = 'A3AuthenticationError';\r\n }\r\n}\r\n\r\nexport class A3RateLimitError extends A3ApiError {\r\n readonly retryAfter: number | undefined;\r\n\r\n constructor(retryAfter?: number, body?: A3ErrorBody) {\r\n super('Rate limit exceeded', 429, body);\r\n this.name = 'A3RateLimitError';\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\nexport class A3ValidationError extends A3ApiError {\r\n readonly validationErrors: string[];\r\n\r\n constructor(body?: A3ErrorBody) {\r\n const errors = body?.message\r\n ? (Array.isArray(body.message) ? body.message : [body.message])\r\n : [];\r\n super(\r\n errors.length > 0\r\n ? `Validation failed: ${errors.join(', ')}`\r\n : 'Validation failed',\r\n 400,\r\n body,\r\n );\r\n this.name = 'A3ValidationError';\r\n this.validationErrors = errors;\r\n }\r\n}\r\n\r\nexport class A3ConnectionError extends Error {\r\n readonly cause: unknown;\r\n\r\n constructor(message: string, cause?: unknown) {\r\n super(message);\r\n this.name = 'A3ConnectionError';\r\n this.cause = cause;\r\n }\r\n}\r\n","const RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);\r\n\r\nexport function isRetryableStatus(status: number): boolean {\r\n return RETRYABLE_STATUS_CODES.has(status);\r\n}\r\n\r\nexport function parseRetryAfter(header: string | null): number | undefined {\r\n if (header == null || header === '') return undefined;\r\n const seconds = Number(header);\r\n if (!Number.isNaN(seconds) && seconds >= 0) {\r\n return seconds * 1000;\r\n }\r\n const date = Date.parse(header);\r\n if (!Number.isNaN(date)) {\r\n const ms = date - Date.now();\r\n return ms > 0 ? ms : 0;\r\n }\r\n return undefined;\r\n}\r\n\r\nexport function calculateDelay(\r\n attempt: number,\r\n baseDelayMs: number = 500,\r\n): number {\r\n const exponential = baseDelayMs * 2 ** attempt;\r\n return Math.random() * exponential;\r\n}\r\n\r\nexport async function withRetry<T>(\r\n fn: () => Promise<T>,\r\n opts: {\r\n maxRetries: number;\r\n shouldRetry: (error: unknown) => { retry: boolean; retryAfterMs?: number };\r\n },\r\n): Promise<T> {\r\n let lastError: unknown;\r\n\r\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\r\n try {\r\n return await fn();\r\n } catch (error) {\r\n lastError = error;\r\n\r\n if (attempt >= opts.maxRetries) break;\r\n\r\n const { retry, retryAfterMs } = opts.shouldRetry(error);\r\n if (!retry) break;\r\n\r\n const delay = retryAfterMs ?? calculateDelay(attempt);\r\n await new Promise((resolve) => setTimeout(resolve, delay));\r\n }\r\n }\r\n\r\n throw lastError;\r\n}\r\n","export const SDK_VERSION = '0.1.0';\r\n","import type {\r\n A3ClientOptions,\r\n A3ErrorBody,\r\n AssessAgeRequest,\r\n AssessAgeResponse,\r\n} from './types.js';\r\nimport {\r\n A3ApiError,\r\n A3AuthenticationError,\r\n A3ConnectionError,\r\n A3RateLimitError,\r\n A3ValidationError,\r\n} from './errors.js';\r\nimport { isRetryableStatus, parseRetryAfter, withRetry } from './retry.js';\r\nimport { SDK_VERSION } from './version.js';\r\n\r\nconst DEFAULT_BASE_URL = 'https://api.a3api.io';\r\nconst DEFAULT_TIMEOUT = 30_000;\r\nconst DEFAULT_MAX_RETRIES = 2;\r\n\r\nexport class A3Client {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n private readonly timeout: number;\r\n private readonly maxRetries: number;\r\n\r\n constructor(options: A3ClientOptions) {\r\n if (!options.apiKey) {\r\n throw new Error('apiKey is required');\r\n }\r\n this.apiKey = options.apiKey;\r\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\r\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\r\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\r\n }\r\n\r\n async assessAge(request: AssessAgeRequest): Promise<AssessAgeResponse> {\r\n return withRetry(() => this._assessAge(request), {\r\n maxRetries: this.maxRetries,\r\n shouldRetry: (error) => {\r\n if (error instanceof A3RateLimitError) {\r\n return { retry: true, retryAfterMs: error.retryAfter };\r\n }\r\n if (error instanceof A3ApiError && isRetryableStatus(error.statusCode)) {\r\n return { retry: true };\r\n }\r\n if (error instanceof A3ConnectionError) {\r\n return { retry: true };\r\n }\r\n return { retry: false };\r\n },\r\n });\r\n }\r\n\r\n private async _assessAge(\r\n request: AssessAgeRequest,\r\n ): Promise<AssessAgeResponse> {\r\n const url = `${this.baseUrl}/v1/assurance/assess-age`;\r\n\r\n let response: Response;\r\n try {\r\n response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': this.apiKey,\r\n 'User-Agent': `a3api-node/${SDK_VERSION}`,\r\n },\r\n body: JSON.stringify(request),\r\n signal: AbortSignal.timeout(this.timeout),\r\n });\r\n } catch (error) {\r\n if (error instanceof DOMException && error.name === 'TimeoutError') {\r\n throw new A3ConnectionError(\r\n `Request timed out after ${this.timeout}ms`,\r\n error,\r\n );\r\n }\r\n throw new A3ConnectionError(\r\n error instanceof Error ? error.message : 'Network request failed',\r\n error,\r\n );\r\n }\r\n\r\n if (response.ok) {\r\n return (await response.json()) as AssessAgeResponse;\r\n }\r\n\r\n let body: A3ErrorBody | undefined;\r\n try {\r\n body = (await response.json()) as A3ErrorBody;\r\n } catch {\r\n // body may not be JSON\r\n }\r\n\r\n switch (response.status) {\r\n case 400:\r\n throw new A3ValidationError(body);\r\n case 401:\r\n throw new A3AuthenticationError(body);\r\n case 429: {\r\n const retryAfter = parseRetryAfter(\r\n response.headers.get('retry-after'),\r\n );\r\n throw new A3RateLimitError(retryAfter, body);\r\n }\r\n default:\r\n throw new A3ApiError(\r\n body?.error ?? `HTTP ${response.status}`,\r\n response.status,\r\n body,\r\n );\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/retry.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export { A3Client } from './client.js';\r\n\r\nexport type {\r\n A3ClientOptions,\r\n A3ErrorBody,\r\n AssessAgeRequest,\r\n AssessAgeResponse,\r\n OsSignal,\r\n Verdict,\r\n AgeBracket,\r\n ParentalConsentStatus,\r\n ConsentSource,\r\n FaceEstimationProvider,\r\n IpType,\r\n ReferrerCategory,\r\n BehavioralMetrics,\r\n DeviceContext,\r\n ContextualSignals,\r\n AccountLongevity,\r\n InputComplexity,\r\n FaceEstimationResult,\r\n} from './types.js';\r\n\r\nexport {\r\n A3ApiError,\r\n A3AuthenticationError,\r\n A3RateLimitError,\r\n A3ValidationError,\r\n A3ConnectionError,\r\n} from './errors.js';\r\n\r\nexport { SDK_VERSION } from './version.js';\r\n","import type { A3ErrorBody } from './types.js';\r\n\r\nexport class A3ApiError extends Error {\r\n readonly statusCode: number;\r\n readonly body: A3ErrorBody | undefined;\r\n\r\n constructor(message: string, statusCode: number, body?: A3ErrorBody) {\r\n super(message);\r\n this.name = 'A3ApiError';\r\n this.statusCode = statusCode;\r\n this.body = body;\r\n }\r\n}\r\n\r\nexport class A3AuthenticationError extends A3ApiError {\r\n constructor(body?: A3ErrorBody) {\r\n super(\r\n body?.message\r\n ? (Array.isArray(body.message) ? body.message.join(', ') : body.message)\r\n : 'Unauthorized',\r\n 401,\r\n body,\r\n );\r\n this.name = 'A3AuthenticationError';\r\n }\r\n}\r\n\r\nexport class A3RateLimitError extends A3ApiError {\r\n readonly retryAfter: number | undefined;\r\n\r\n constructor(retryAfter?: number, body?: A3ErrorBody) {\r\n super('Rate limit exceeded', 429, body);\r\n this.name = 'A3RateLimitError';\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\nexport class A3ValidationError extends A3ApiError {\r\n readonly validationErrors: string[];\r\n\r\n constructor(body?: A3ErrorBody) {\r\n const errors = body?.message\r\n ? (Array.isArray(body.message) ? body.message : [body.message])\r\n : [];\r\n super(\r\n errors.length > 0\r\n ? `Validation failed: ${errors.join(', ')}`\r\n : 'Validation failed',\r\n 400,\r\n body,\r\n );\r\n this.name = 'A3ValidationError';\r\n this.validationErrors = errors;\r\n }\r\n}\r\n\r\nexport class A3ConnectionError extends Error {\r\n readonly cause: unknown;\r\n\r\n constructor(message: string, cause?: unknown) {\r\n super(message);\r\n this.name = 'A3ConnectionError';\r\n this.cause = cause;\r\n }\r\n}\r\n","const RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);\r\n\r\nexport function isRetryableStatus(status: number): boolean {\r\n return RETRYABLE_STATUS_CODES.has(status);\r\n}\r\n\r\nexport function parseRetryAfter(header: string | null): number | undefined {\r\n if (header == null || header === '') return undefined;\r\n const seconds = Number(header);\r\n if (!Number.isNaN(seconds) && seconds >= 0) {\r\n return seconds * 1000;\r\n }\r\n const date = Date.parse(header);\r\n if (!Number.isNaN(date)) {\r\n const ms = date - Date.now();\r\n return ms > 0 ? ms : 0;\r\n }\r\n return undefined;\r\n}\r\n\r\nexport function calculateDelay(\r\n attempt: number,\r\n baseDelayMs: number = 500,\r\n): number {\r\n const exponential = baseDelayMs * 2 ** attempt;\r\n return Math.random() * exponential;\r\n}\r\n\r\nexport async function withRetry<T>(\r\n fn: () => Promise<T>,\r\n opts: {\r\n maxRetries: number;\r\n shouldRetry: (error: unknown) => { retry: boolean; retryAfterMs?: number };\r\n },\r\n): Promise<T> {\r\n let lastError: unknown;\r\n\r\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\r\n try {\r\n return await fn();\r\n } catch (error) {\r\n lastError = error;\r\n\r\n if (attempt >= opts.maxRetries) break;\r\n\r\n const { retry, retryAfterMs } = opts.shouldRetry(error);\r\n if (!retry) break;\r\n\r\n const delay = retryAfterMs ?? calculateDelay(attempt);\r\n await new Promise((resolve) => setTimeout(resolve, delay));\r\n }\r\n }\r\n\r\n throw lastError;\r\n}\r\n","export const SDK_VERSION = '0.1.2';\r\n","import type {\r\n A3ClientOptions,\r\n A3ErrorBody,\r\n AssessAgeRequest,\r\n AssessAgeResponse,\r\n} from './types.js';\r\nimport {\r\n A3ApiError,\r\n A3AuthenticationError,\r\n A3ConnectionError,\r\n A3RateLimitError,\r\n A3ValidationError,\r\n} from './errors.js';\r\nimport { isRetryableStatus, parseRetryAfter, withRetry } from './retry.js';\r\nimport { SDK_VERSION } from './version.js';\r\n\r\nconst DEFAULT_BASE_URL = 'https://api.a3api.io';\r\nconst DEFAULT_TIMEOUT = 30_000;\r\nconst DEFAULT_MAX_RETRIES = 2;\r\n\r\nexport class A3Client {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n private readonly timeout: number;\r\n private readonly maxRetries: number;\r\n\r\n constructor(options: A3ClientOptions) {\r\n if (!options.apiKey) {\r\n throw new Error('apiKey is required');\r\n }\r\n this.apiKey = options.apiKey;\r\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\r\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\r\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\r\n }\r\n\r\n async assessAge(request: AssessAgeRequest): Promise<AssessAgeResponse> {\r\n return withRetry(() => this._assessAge(request), {\r\n maxRetries: this.maxRetries,\r\n shouldRetry: (error) => {\r\n if (error instanceof A3RateLimitError) {\r\n return { retry: true, retryAfterMs: error.retryAfter };\r\n }\r\n if (error instanceof A3ApiError && isRetryableStatus(error.statusCode)) {\r\n return { retry: true };\r\n }\r\n if (error instanceof A3ConnectionError) {\r\n return { retry: true };\r\n }\r\n return { retry: false };\r\n },\r\n });\r\n }\r\n\r\n private async _assessAge(\r\n request: AssessAgeRequest,\r\n ): Promise<AssessAgeResponse> {\r\n const url = `${this.baseUrl}/v1/assurance/assess-age`;\r\n\r\n let response: Response;\r\n try {\r\n response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n Authorization: `Bearer ${this.apiKey}`,\r\n 'User-Agent': `a3api-node/${SDK_VERSION}`,\r\n },\r\n body: JSON.stringify(request),\r\n signal: AbortSignal.timeout(this.timeout),\r\n });\r\n } catch (error) {\r\n if (error instanceof DOMException && error.name === 'TimeoutError') {\r\n throw new A3ConnectionError(\r\n `Request timed out after ${this.timeout}ms`,\r\n error,\r\n );\r\n }\r\n throw new A3ConnectionError(\r\n error instanceof Error ? error.message : 'Network request failed',\r\n error,\r\n );\r\n }\r\n\r\n if (response.ok) {\r\n return (await response.json()) as AssessAgeResponse;\r\n }\r\n\r\n let body: A3ErrorBody | undefined;\r\n try {\r\n body = (await response.json()) as A3ErrorBody;\r\n } catch {\r\n // body may not be JSON\r\n }\r\n\r\n switch (response.status) {\r\n case 400:\r\n throw new A3ValidationError(body);\r\n case 401:\r\n throw new A3AuthenticationError(body);\r\n case 429: {\r\n const retryAfter = parseRetryAfter(\r\n response.headers.get('retry-after'),\r\n );\r\n throw new A3RateLimitError(retryAfter, body);\r\n }\r\n default:\r\n throw new A3ApiError(\r\n body?.error ?? `HTTP ${response.status}`,\r\n response.status,\r\n body,\r\n );\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -106,6 +106,6 @@ declare class A3ConnectionError extends Error {
106
106
  constructor(message: string, cause?: unknown);
107
107
  }
108
108
 
109
- declare const SDK_VERSION = "0.1.0";
109
+ declare const SDK_VERSION = "0.1.2";
110
110
 
111
111
  export { A3ApiError, A3AuthenticationError, A3Client, type A3ClientOptions, A3ConnectionError, type A3ErrorBody, A3RateLimitError, A3ValidationError, type AccountLongevity, type AgeBracket, type AssessAgeRequest, type AssessAgeResponse, type BehavioralMetrics, type ConsentSource, type ContextualSignals, type DeviceContext, type FaceEstimationProvider, type FaceEstimationResult, type InputComplexity, type IpType, type OsSignal, type ParentalConsentStatus, type ReferrerCategory, SDK_VERSION, type Verdict };
package/dist/index.d.ts CHANGED
@@ -106,6 +106,6 @@ declare class A3ConnectionError extends Error {
106
106
  constructor(message: string, cause?: unknown);
107
107
  }
108
108
 
109
- declare const SDK_VERSION = "0.1.0";
109
+ declare const SDK_VERSION = "0.1.2";
110
110
 
111
111
  export { A3ApiError, A3AuthenticationError, A3Client, type A3ClientOptions, A3ConnectionError, type A3ErrorBody, A3RateLimitError, A3ValidationError, type AccountLongevity, type AgeBracket, type AssessAgeRequest, type AssessAgeResponse, type BehavioralMetrics, type ConsentSource, type ContextualSignals, type DeviceContext, type FaceEstimationProvider, type FaceEstimationResult, type InputComplexity, type IpType, type OsSignal, type ParentalConsentStatus, type ReferrerCategory, SDK_VERSION, type Verdict };
package/dist/index.js CHANGED
@@ -89,7 +89,7 @@ async function withRetry(fn, opts) {
89
89
  }
90
90
 
91
91
  // src/version.ts
92
- var SDK_VERSION = "0.1.0";
92
+ var SDK_VERSION = "0.1.2";
93
93
 
94
94
  // src/client.ts
95
95
  var DEFAULT_BASE_URL = "https://api.a3api.io";
@@ -134,7 +134,7 @@ var A3Client = class {
134
134
  method: "POST",
135
135
  headers: {
136
136
  "Content-Type": "application/json",
137
- "x-api-key": this.apiKey,
137
+ Authorization: `Bearer ${this.apiKey}`,
138
138
  "User-Agent": `a3api-node/${SDK_VERSION}`
139
139
  },
140
140
  body: JSON.stringify(request),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/retry.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["import type { A3ErrorBody } from './types.js';\r\n\r\nexport class A3ApiError extends Error {\r\n readonly statusCode: number;\r\n readonly body: A3ErrorBody | undefined;\r\n\r\n constructor(message: string, statusCode: number, body?: A3ErrorBody) {\r\n super(message);\r\n this.name = 'A3ApiError';\r\n this.statusCode = statusCode;\r\n this.body = body;\r\n }\r\n}\r\n\r\nexport class A3AuthenticationError extends A3ApiError {\r\n constructor(body?: A3ErrorBody) {\r\n super(\r\n body?.message\r\n ? (Array.isArray(body.message) ? body.message.join(', ') : body.message)\r\n : 'Unauthorized',\r\n 401,\r\n body,\r\n );\r\n this.name = 'A3AuthenticationError';\r\n }\r\n}\r\n\r\nexport class A3RateLimitError extends A3ApiError {\r\n readonly retryAfter: number | undefined;\r\n\r\n constructor(retryAfter?: number, body?: A3ErrorBody) {\r\n super('Rate limit exceeded', 429, body);\r\n this.name = 'A3RateLimitError';\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\nexport class A3ValidationError extends A3ApiError {\r\n readonly validationErrors: string[];\r\n\r\n constructor(body?: A3ErrorBody) {\r\n const errors = body?.message\r\n ? (Array.isArray(body.message) ? body.message : [body.message])\r\n : [];\r\n super(\r\n errors.length > 0\r\n ? `Validation failed: ${errors.join(', ')}`\r\n : 'Validation failed',\r\n 400,\r\n body,\r\n );\r\n this.name = 'A3ValidationError';\r\n this.validationErrors = errors;\r\n }\r\n}\r\n\r\nexport class A3ConnectionError extends Error {\r\n readonly cause: unknown;\r\n\r\n constructor(message: string, cause?: unknown) {\r\n super(message);\r\n this.name = 'A3ConnectionError';\r\n this.cause = cause;\r\n }\r\n}\r\n","const RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);\r\n\r\nexport function isRetryableStatus(status: number): boolean {\r\n return RETRYABLE_STATUS_CODES.has(status);\r\n}\r\n\r\nexport function parseRetryAfter(header: string | null): number | undefined {\r\n if (header == null || header === '') return undefined;\r\n const seconds = Number(header);\r\n if (!Number.isNaN(seconds) && seconds >= 0) {\r\n return seconds * 1000;\r\n }\r\n const date = Date.parse(header);\r\n if (!Number.isNaN(date)) {\r\n const ms = date - Date.now();\r\n return ms > 0 ? ms : 0;\r\n }\r\n return undefined;\r\n}\r\n\r\nexport function calculateDelay(\r\n attempt: number,\r\n baseDelayMs: number = 500,\r\n): number {\r\n const exponential = baseDelayMs * 2 ** attempt;\r\n return Math.random() * exponential;\r\n}\r\n\r\nexport async function withRetry<T>(\r\n fn: () => Promise<T>,\r\n opts: {\r\n maxRetries: number;\r\n shouldRetry: (error: unknown) => { retry: boolean; retryAfterMs?: number };\r\n },\r\n): Promise<T> {\r\n let lastError: unknown;\r\n\r\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\r\n try {\r\n return await fn();\r\n } catch (error) {\r\n lastError = error;\r\n\r\n if (attempt >= opts.maxRetries) break;\r\n\r\n const { retry, retryAfterMs } = opts.shouldRetry(error);\r\n if (!retry) break;\r\n\r\n const delay = retryAfterMs ?? calculateDelay(attempt);\r\n await new Promise((resolve) => setTimeout(resolve, delay));\r\n }\r\n }\r\n\r\n throw lastError;\r\n}\r\n","export const SDK_VERSION = '0.1.0';\r\n","import type {\r\n A3ClientOptions,\r\n A3ErrorBody,\r\n AssessAgeRequest,\r\n AssessAgeResponse,\r\n} from './types.js';\r\nimport {\r\n A3ApiError,\r\n A3AuthenticationError,\r\n A3ConnectionError,\r\n A3RateLimitError,\r\n A3ValidationError,\r\n} from './errors.js';\r\nimport { isRetryableStatus, parseRetryAfter, withRetry } from './retry.js';\r\nimport { SDK_VERSION } from './version.js';\r\n\r\nconst DEFAULT_BASE_URL = 'https://api.a3api.io';\r\nconst DEFAULT_TIMEOUT = 30_000;\r\nconst DEFAULT_MAX_RETRIES = 2;\r\n\r\nexport class A3Client {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n private readonly timeout: number;\r\n private readonly maxRetries: number;\r\n\r\n constructor(options: A3ClientOptions) {\r\n if (!options.apiKey) {\r\n throw new Error('apiKey is required');\r\n }\r\n this.apiKey = options.apiKey;\r\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\r\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\r\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\r\n }\r\n\r\n async assessAge(request: AssessAgeRequest): Promise<AssessAgeResponse> {\r\n return withRetry(() => this._assessAge(request), {\r\n maxRetries: this.maxRetries,\r\n shouldRetry: (error) => {\r\n if (error instanceof A3RateLimitError) {\r\n return { retry: true, retryAfterMs: error.retryAfter };\r\n }\r\n if (error instanceof A3ApiError && isRetryableStatus(error.statusCode)) {\r\n return { retry: true };\r\n }\r\n if (error instanceof A3ConnectionError) {\r\n return { retry: true };\r\n }\r\n return { retry: false };\r\n },\r\n });\r\n }\r\n\r\n private async _assessAge(\r\n request: AssessAgeRequest,\r\n ): Promise<AssessAgeResponse> {\r\n const url = `${this.baseUrl}/v1/assurance/assess-age`;\r\n\r\n let response: Response;\r\n try {\r\n response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': this.apiKey,\r\n 'User-Agent': `a3api-node/${SDK_VERSION}`,\r\n },\r\n body: JSON.stringify(request),\r\n signal: AbortSignal.timeout(this.timeout),\r\n });\r\n } catch (error) {\r\n if (error instanceof DOMException && error.name === 'TimeoutError') {\r\n throw new A3ConnectionError(\r\n `Request timed out after ${this.timeout}ms`,\r\n error,\r\n );\r\n }\r\n throw new A3ConnectionError(\r\n error instanceof Error ? error.message : 'Network request failed',\r\n error,\r\n );\r\n }\r\n\r\n if (response.ok) {\r\n return (await response.json()) as AssessAgeResponse;\r\n }\r\n\r\n let body: A3ErrorBody | undefined;\r\n try {\r\n body = (await response.json()) as A3ErrorBody;\r\n } catch {\r\n // body may not be JSON\r\n }\r\n\r\n switch (response.status) {\r\n case 400:\r\n throw new A3ValidationError(body);\r\n case 401:\r\n throw new A3AuthenticationError(body);\r\n case 429: {\r\n const retryAfter = parseRetryAfter(\r\n response.headers.get('retry-after'),\r\n );\r\n throw new A3RateLimitError(retryAfter, body);\r\n }\r\n default:\r\n throw new A3ApiError(\r\n body?.error ?? `HTTP ${response.status}`,\r\n response.status,\r\n body,\r\n );\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/retry.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["import type { A3ErrorBody } from './types.js';\r\n\r\nexport class A3ApiError extends Error {\r\n readonly statusCode: number;\r\n readonly body: A3ErrorBody | undefined;\r\n\r\n constructor(message: string, statusCode: number, body?: A3ErrorBody) {\r\n super(message);\r\n this.name = 'A3ApiError';\r\n this.statusCode = statusCode;\r\n this.body = body;\r\n }\r\n}\r\n\r\nexport class A3AuthenticationError extends A3ApiError {\r\n constructor(body?: A3ErrorBody) {\r\n super(\r\n body?.message\r\n ? (Array.isArray(body.message) ? body.message.join(', ') : body.message)\r\n : 'Unauthorized',\r\n 401,\r\n body,\r\n );\r\n this.name = 'A3AuthenticationError';\r\n }\r\n}\r\n\r\nexport class A3RateLimitError extends A3ApiError {\r\n readonly retryAfter: number | undefined;\r\n\r\n constructor(retryAfter?: number, body?: A3ErrorBody) {\r\n super('Rate limit exceeded', 429, body);\r\n this.name = 'A3RateLimitError';\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\nexport class A3ValidationError extends A3ApiError {\r\n readonly validationErrors: string[];\r\n\r\n constructor(body?: A3ErrorBody) {\r\n const errors = body?.message\r\n ? (Array.isArray(body.message) ? body.message : [body.message])\r\n : [];\r\n super(\r\n errors.length > 0\r\n ? `Validation failed: ${errors.join(', ')}`\r\n : 'Validation failed',\r\n 400,\r\n body,\r\n );\r\n this.name = 'A3ValidationError';\r\n this.validationErrors = errors;\r\n }\r\n}\r\n\r\nexport class A3ConnectionError extends Error {\r\n readonly cause: unknown;\r\n\r\n constructor(message: string, cause?: unknown) {\r\n super(message);\r\n this.name = 'A3ConnectionError';\r\n this.cause = cause;\r\n }\r\n}\r\n","const RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);\r\n\r\nexport function isRetryableStatus(status: number): boolean {\r\n return RETRYABLE_STATUS_CODES.has(status);\r\n}\r\n\r\nexport function parseRetryAfter(header: string | null): number | undefined {\r\n if (header == null || header === '') return undefined;\r\n const seconds = Number(header);\r\n if (!Number.isNaN(seconds) && seconds >= 0) {\r\n return seconds * 1000;\r\n }\r\n const date = Date.parse(header);\r\n if (!Number.isNaN(date)) {\r\n const ms = date - Date.now();\r\n return ms > 0 ? ms : 0;\r\n }\r\n return undefined;\r\n}\r\n\r\nexport function calculateDelay(\r\n attempt: number,\r\n baseDelayMs: number = 500,\r\n): number {\r\n const exponential = baseDelayMs * 2 ** attempt;\r\n return Math.random() * exponential;\r\n}\r\n\r\nexport async function withRetry<T>(\r\n fn: () => Promise<T>,\r\n opts: {\r\n maxRetries: number;\r\n shouldRetry: (error: unknown) => { retry: boolean; retryAfterMs?: number };\r\n },\r\n): Promise<T> {\r\n let lastError: unknown;\r\n\r\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\r\n try {\r\n return await fn();\r\n } catch (error) {\r\n lastError = error;\r\n\r\n if (attempt >= opts.maxRetries) break;\r\n\r\n const { retry, retryAfterMs } = opts.shouldRetry(error);\r\n if (!retry) break;\r\n\r\n const delay = retryAfterMs ?? calculateDelay(attempt);\r\n await new Promise((resolve) => setTimeout(resolve, delay));\r\n }\r\n }\r\n\r\n throw lastError;\r\n}\r\n","export const SDK_VERSION = '0.1.2';\r\n","import type {\r\n A3ClientOptions,\r\n A3ErrorBody,\r\n AssessAgeRequest,\r\n AssessAgeResponse,\r\n} from './types.js';\r\nimport {\r\n A3ApiError,\r\n A3AuthenticationError,\r\n A3ConnectionError,\r\n A3RateLimitError,\r\n A3ValidationError,\r\n} from './errors.js';\r\nimport { isRetryableStatus, parseRetryAfter, withRetry } from './retry.js';\r\nimport { SDK_VERSION } from './version.js';\r\n\r\nconst DEFAULT_BASE_URL = 'https://api.a3api.io';\r\nconst DEFAULT_TIMEOUT = 30_000;\r\nconst DEFAULT_MAX_RETRIES = 2;\r\n\r\nexport class A3Client {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n private readonly timeout: number;\r\n private readonly maxRetries: number;\r\n\r\n constructor(options: A3ClientOptions) {\r\n if (!options.apiKey) {\r\n throw new Error('apiKey is required');\r\n }\r\n this.apiKey = options.apiKey;\r\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\r\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\r\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\r\n }\r\n\r\n async assessAge(request: AssessAgeRequest): Promise<AssessAgeResponse> {\r\n return withRetry(() => this._assessAge(request), {\r\n maxRetries: this.maxRetries,\r\n shouldRetry: (error) => {\r\n if (error instanceof A3RateLimitError) {\r\n return { retry: true, retryAfterMs: error.retryAfter };\r\n }\r\n if (error instanceof A3ApiError && isRetryableStatus(error.statusCode)) {\r\n return { retry: true };\r\n }\r\n if (error instanceof A3ConnectionError) {\r\n return { retry: true };\r\n }\r\n return { retry: false };\r\n },\r\n });\r\n }\r\n\r\n private async _assessAge(\r\n request: AssessAgeRequest,\r\n ): Promise<AssessAgeResponse> {\r\n const url = `${this.baseUrl}/v1/assurance/assess-age`;\r\n\r\n let response: Response;\r\n try {\r\n response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n Authorization: `Bearer ${this.apiKey}`,\r\n 'User-Agent': `a3api-node/${SDK_VERSION}`,\r\n },\r\n body: JSON.stringify(request),\r\n signal: AbortSignal.timeout(this.timeout),\r\n });\r\n } catch (error) {\r\n if (error instanceof DOMException && error.name === 'TimeoutError') {\r\n throw new A3ConnectionError(\r\n `Request timed out after ${this.timeout}ms`,\r\n error,\r\n );\r\n }\r\n throw new A3ConnectionError(\r\n error instanceof Error ? error.message : 'Network request failed',\r\n error,\r\n );\r\n }\r\n\r\n if (response.ok) {\r\n return (await response.json()) as AssessAgeResponse;\r\n }\r\n\r\n let body: A3ErrorBody | undefined;\r\n try {\r\n body = (await response.json()) as A3ErrorBody;\r\n } catch {\r\n // body may not be JSON\r\n }\r\n\r\n switch (response.status) {\r\n case 400:\r\n throw new A3ValidationError(body);\r\n case 401:\r\n throw new A3AuthenticationError(body);\r\n case 429: {\r\n const retryAfter = parseRetryAfter(\r\n response.headers.get('retry-after'),\r\n );\r\n throw new A3RateLimitError(retryAfter, body);\r\n }\r\n default:\r\n throw new A3ApiError(\r\n body?.error ?? `HTTP ${response.status}`,\r\n response.status,\r\n body,\r\n );\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a3api/node",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Official Node.js client for the A3 Age Assurance API",
5
5
  "private": false,
6
6
  "type": "module",