@builtwith/sdk 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/package.json +1 -1
- package/src/index.js +48 -68
package/README.md
CHANGED
|
@@ -60,6 +60,9 @@ if (result.ok) {
|
|
|
60
60
|
| `financial({ lookup })` | Root domain | Financial data |
|
|
61
61
|
| `social({ lookup })` | Root domain | Social profile related domains |
|
|
62
62
|
| `vector_search({ query, limit? })` | Search query | Semantic technology/category search |
|
|
63
|
+
| `payment_discovery()` | — | Agent Payment API: credit balance |
|
|
64
|
+
| `payment_configuration()` | — | Agent Payment API: spending limits |
|
|
65
|
+
| `payment_purchase({ credits })` | Integer ≥ 2000 | Agent Payment API: purchase credits |
|
|
63
66
|
|
|
64
67
|
### Response Format
|
|
65
68
|
|
|
@@ -126,6 +129,9 @@ All methods accept a `CancellationToken` as an optional last parameter.
|
|
|
126
129
|
| `financial(lookup)` | `string` | Financial data |
|
|
127
130
|
| `social(lookup)` | `string` | Social profile related domains |
|
|
128
131
|
| `vector_search(query, limit?)` | `string`, `int?` | Semantic technology/category search |
|
|
132
|
+
| `payment_discovery()` | — | Agent Payment API: credit balance |
|
|
133
|
+
| `payment_configuration()` | — | Agent Payment API: spending limits |
|
|
134
|
+
| `payment_purchase(credits)` | `int` ≥ 2000 | Agent Payment API: purchase credits |
|
|
129
135
|
|
|
130
136
|
### Response Format
|
|
131
137
|
|
|
@@ -148,6 +154,23 @@ BUILTWITH_API_KEY=your-key dotnet run
|
|
|
148
154
|
|
|
149
155
|
---
|
|
150
156
|
|
|
157
|
+
## Agent Payment API
|
|
158
|
+
|
|
159
|
+
The payment methods let AI agents check credit balances, view spending configuration, and purchase credits. They route through the standard MCP endpoint using your existing API key. Configure billing at [payments.builtwith.com/agent-payment-api-config](https://payments.builtwith.com/agent-payment-api-config).
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
// Node.js
|
|
163
|
+
const result = await client.payment_discovery();
|
|
164
|
+
// result.data => { credits_total, credits_used, credits_available }
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
```csharp
|
|
168
|
+
// C#
|
|
169
|
+
var result = await client.payment_discovery();
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
151
174
|
## Prompt Helpers
|
|
152
175
|
|
|
153
176
|
Both SDKs include prompt helper methods for use with AI agents:
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -7,7 +7,6 @@ const { URL } = require('url');
|
|
|
7
7
|
// ── Constants ──────────────────────────────────────────────────────────────────
|
|
8
8
|
|
|
9
9
|
const MCP_ENDPOINT = 'https://api.builtwith.com/mcp';
|
|
10
|
-
const PAYMENTS_ENDPOINT = 'https://payments.builtwith.com';
|
|
11
10
|
const MAX_RETRIES = 3;
|
|
12
11
|
const INITIAL_BACKOFF_MS = 1000;
|
|
13
12
|
const DOMAIN_RE = /^(?!-)[a-zA-Z0-9-]{1,63}(?<!-)(\.[a-zA-Z]{2,})+$/;
|
|
@@ -134,37 +133,6 @@ function _http_post(url_str, body, headers, timeout_ms) {
|
|
|
134
133
|
});
|
|
135
134
|
}
|
|
136
135
|
|
|
137
|
-
function _http_get(url_str, headers, timeout_ms) {
|
|
138
|
-
return new Promise((resolve, reject) => {
|
|
139
|
-
const parsed = new URL(url_str);
|
|
140
|
-
const transport = parsed.protocol === 'http:' ? http : https;
|
|
141
|
-
const opts = {
|
|
142
|
-
hostname: parsed.hostname,
|
|
143
|
-
port: parsed.port || (parsed.protocol === 'http:' ? 80 : 443),
|
|
144
|
-
path: parsed.pathname + parsed.search,
|
|
145
|
-
method: 'GET',
|
|
146
|
-
headers: {
|
|
147
|
-
...headers,
|
|
148
|
-
'Accept': 'application/json',
|
|
149
|
-
},
|
|
150
|
-
timeout: timeout_ms,
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const req = transport.request(opts, (res) => {
|
|
154
|
-
const chunks = [];
|
|
155
|
-
res.on('data', chunk => chunks.push(chunk));
|
|
156
|
-
res.on('end', () => {
|
|
157
|
-
const raw_body = Buffer.concat(chunks).toString('utf-8');
|
|
158
|
-
resolve({ status: res.statusCode, headers: res.headers, body: raw_body });
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
req.on('error', reject);
|
|
163
|
-
req.on('timeout', () => { req.destroy(); reject(new Error('Request timed out')); });
|
|
164
|
-
req.end();
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
136
|
// ── Client ─────────────────────────────────────────────────────────────────────
|
|
169
137
|
|
|
170
138
|
class BuiltWithClient {
|
|
@@ -174,7 +142,6 @@ class BuiltWithClient {
|
|
|
174
142
|
}
|
|
175
143
|
this._api_key = api_key;
|
|
176
144
|
this._endpoint = options.endpoint || MCP_ENDPOINT;
|
|
177
|
-
this._payments_endpoint = options.payments_endpoint || PAYMENTS_ENDPOINT;
|
|
178
145
|
this._max_retries = options.max_retries != null ? options.max_retries : MAX_RETRIES;
|
|
179
146
|
this._timeout_ms = options.timeout_ms || 30000;
|
|
180
147
|
}
|
|
@@ -271,38 +238,6 @@ class BuiltWithClient {
|
|
|
271
238
|
return _err(last_error || new BuiltWithError('UNKNOWN_ERROR', 'Request failed', 0), mcp_tool);
|
|
272
239
|
}
|
|
273
240
|
|
|
274
|
-
// ── Payment API ────────────────────────────────────────────────────────────
|
|
275
|
-
|
|
276
|
-
async _payment_request(method, path, body = null) {
|
|
277
|
-
const url = this._payments_endpoint + path;
|
|
278
|
-
const headers = { Authorization: `Bearer ${this._api_key}` };
|
|
279
|
-
try {
|
|
280
|
-
const res = method === 'GET'
|
|
281
|
-
? await _http_get(url, headers, this._timeout_ms)
|
|
282
|
-
: await _http_post(url, body, headers, this._timeout_ms);
|
|
283
|
-
|
|
284
|
-
const status = res.status;
|
|
285
|
-
|
|
286
|
-
if (status === 400) return _err(new BuiltWithError('VALIDATION_ERROR', `HTTP 400: ${res.body.substring(0, 200)}`, status, null, 'Check request parameters.'), path);
|
|
287
|
-
if (status === 401 || status === 403) return _err(new BuiltWithError('AUTH_ERROR', 'Authentication failed. Check your API key.', status, null, 'Verify your BuiltWith API key is correct and active.'), path);
|
|
288
|
-
if (status === 402) return _err(new BuiltWithError('PAYMENT_FAILED', `HTTP 402: ${res.body.substring(0, 200)}`, status, null, 'Payment could not be processed. Check your billing details at payments.builtwith.com/agent-payment-api-config.'), path);
|
|
289
|
-
if (status === 405) return _err(new BuiltWithError('METHOD_NOT_ALLOWED', `HTTP 405: wrong HTTP method.`, status), path);
|
|
290
|
-
if (status >= 500) return _err(new BuiltWithError('SERVER_ERROR', `HTTP ${status}: ${res.body.substring(0, 200)}`, status, null, 'The server encountered an error. Try again later.'), path);
|
|
291
|
-
if (status < 200 || status >= 300) return _err(new BuiltWithError('HTTP_ERROR', `HTTP ${status}: ${res.body.substring(0, 200)}`, status), path);
|
|
292
|
-
|
|
293
|
-
let parsed;
|
|
294
|
-
try {
|
|
295
|
-
parsed = JSON.parse(res.body);
|
|
296
|
-
} catch (_) {
|
|
297
|
-
return _err(new BuiltWithError('PARSE_ERROR', 'Failed to parse response JSON.', status), path);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return _ok(parsed, parsed, path);
|
|
301
|
-
} catch (err) {
|
|
302
|
-
return _err(new BuiltWithError('NETWORK_ERROR', err.message, 0, null, 'Check network connectivity.'), path);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
241
|
// ── Public SDK methods ─────────────────────────────────────────────────────
|
|
307
242
|
|
|
308
243
|
async domain_lookup_live(params) {
|
|
@@ -395,12 +330,22 @@ class BuiltWithClient {
|
|
|
395
330
|
return this._request('vector-search', { query, ...(limit != null ? { limit } : {}) });
|
|
396
331
|
}
|
|
397
332
|
|
|
333
|
+
async keyword_search(params) {
|
|
334
|
+
const { keyword, limit, offset } = params || {};
|
|
335
|
+
_validate_string('keyword', keyword);
|
|
336
|
+
return this._request('keyword-search-api', {
|
|
337
|
+
keyword,
|
|
338
|
+
...(limit != null ? { limit } : {}),
|
|
339
|
+
...(offset != null ? { offset } : {}),
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
398
343
|
async payment_discovery() {
|
|
399
|
-
return this.
|
|
344
|
+
return this._request('payment-balance', {});
|
|
400
345
|
}
|
|
401
346
|
|
|
402
347
|
async payment_configuration() {
|
|
403
|
-
return this.
|
|
348
|
+
return this._request('payment-config', {});
|
|
404
349
|
}
|
|
405
350
|
|
|
406
351
|
async payment_purchase(params) {
|
|
@@ -414,7 +359,7 @@ class BuiltWithClient {
|
|
|
414
359
|
if (credits < 2000) {
|
|
415
360
|
throw new BuiltWithError('VALIDATION_ERROR', 'credits must be at least 2000.', 0, null, 'Minimum purchase is 2000 credits.');
|
|
416
361
|
}
|
|
417
|
-
return this.
|
|
362
|
+
return this._request('payment-purchase', { credits });
|
|
418
363
|
}
|
|
419
364
|
|
|
420
365
|
// ── Prompt helpers ─────────────────────────────────────────────────────────
|
|
@@ -448,6 +393,41 @@ class BuiltWithClient {
|
|
|
448
393
|
_validate_domain(domain);
|
|
449
394
|
return { mcp_prompt: 'check-domain-trust', arguments: { domain } };
|
|
450
395
|
}
|
|
396
|
+
|
|
397
|
+
// ── Agent Device-Code Authorization (no API key required) ─────────────────
|
|
398
|
+
|
|
399
|
+
static async agent_auth_start() {
|
|
400
|
+
try {
|
|
401
|
+
const res = await _http_post('https://api.builtwith.com/agent-auth/start', {}, {}, 30000);
|
|
402
|
+
if (res.status < 200 || res.status >= 300) {
|
|
403
|
+
return _err(new BuiltWithError('HTTP_ERROR', `HTTP ${res.status}: ${res.body.substring(0, 200)}`, res.status), 'agent-auth-start');
|
|
404
|
+
}
|
|
405
|
+
let data;
|
|
406
|
+
try { data = JSON.parse(res.body); } catch (_) {
|
|
407
|
+
return _err(new BuiltWithError('PARSE_ERROR', 'Failed to parse agent-auth-start response.', res.status), 'agent-auth-start');
|
|
408
|
+
}
|
|
409
|
+
return _ok(data, data, 'agent-auth-start');
|
|
410
|
+
} catch (err) {
|
|
411
|
+
return _err(new BuiltWithError('NETWORK_ERROR', err.message, 0, null, 'Check network connectivity.'), 'agent-auth-start');
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
static async agent_auth_token(device_code) {
|
|
416
|
+
_validate_string('device_code', device_code);
|
|
417
|
+
try {
|
|
418
|
+
const res = await _http_post('https://api.builtwith.com/agent-auth/token', { device_code }, {}, 30000);
|
|
419
|
+
if (res.status < 200 || res.status >= 300) {
|
|
420
|
+
return _err(new BuiltWithError('HTTP_ERROR', `HTTP ${res.status}: ${res.body.substring(0, 200)}`, res.status), 'agent-auth-token');
|
|
421
|
+
}
|
|
422
|
+
let data;
|
|
423
|
+
try { data = JSON.parse(res.body); } catch (_) {
|
|
424
|
+
return _err(new BuiltWithError('PARSE_ERROR', 'Failed to parse agent-auth-token response.', res.status), 'agent-auth-token');
|
|
425
|
+
}
|
|
426
|
+
return _ok(data, data, 'agent-auth-token');
|
|
427
|
+
} catch (err) {
|
|
428
|
+
return _err(new BuiltWithError('NETWORK_ERROR', err.message, 0, null, 'Check network connectivity.'), 'agent-auth-token');
|
|
429
|
+
}
|
|
430
|
+
}
|
|
451
431
|
}
|
|
452
432
|
|
|
453
433
|
module.exports = { BuiltWithClient, BuiltWithError };
|