@builtwith/sdk 1.0.1 → 1.2.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 CHANGED
@@ -59,6 +59,7 @@ if (result.ok) {
59
59
  | `trust({ lookup })` | Root domain | Trust scoring |
60
60
  | `financial({ lookup })` | Root domain | Financial data |
61
61
  | `social({ lookup })` | Root domain | Social profile related domains |
62
+ | `vector_search({ query, limit? })` | Search query | Semantic technology/category search |
62
63
 
63
64
  ### Response Format
64
65
 
@@ -124,6 +125,7 @@ All methods accept a `CancellationToken` as an optional last parameter.
124
125
  | `trust(lookup)` | `string` | Trust scoring |
125
126
  | `financial(lookup)` | `string` | Financial data |
126
127
  | `social(lookup)` | `string` | Social profile related domains |
128
+ | `vector_search(query, limit?)` | `string`, `int?` | Semantic technology/category search |
127
129
 
128
130
  ### Response Format
129
131
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@builtwith/sdk",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "BuiltWith AI-first SDK for Node.js",
5
5
  "main": "src/index.js",
6
6
  "exports": {
package/src/index.js CHANGED
@@ -1,11 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  const https = require('https');
4
+ const http = require('http');
4
5
  const { URL } = require('url');
5
6
 
6
7
  // ── Constants ──────────────────────────────────────────────────────────────────
7
8
 
8
9
  const MCP_ENDPOINT = 'https://api.builtwith.com/mcp';
10
+ const PAYMENTS_ENDPOINT = 'https://payments.builtwith.com';
9
11
  const MAX_RETRIES = 3;
10
12
  const INITIAL_BACKOFF_MS = 1000;
11
13
  const DOMAIN_RE = /^(?!-)[a-zA-Z0-9-]{1,63}(?<!-)(\.[a-zA-Z]{2,})+$/;
@@ -100,10 +102,11 @@ function _parse_sse_body(raw_body) {
100
102
  function _http_post(url_str, body, headers, timeout_ms) {
101
103
  return new Promise((resolve, reject) => {
102
104
  const parsed = new URL(url_str);
105
+ const transport = parsed.protocol === 'http:' ? http : https;
103
106
  const payload = JSON.stringify(body);
104
107
  const opts = {
105
108
  hostname: parsed.hostname,
106
- port: parsed.port || 443,
109
+ port: parsed.port || (parsed.protocol === 'http:' ? 80 : 443),
107
110
  path: parsed.pathname + parsed.search,
108
111
  method: 'POST',
109
112
  headers: {
@@ -115,7 +118,7 @@ function _http_post(url_str, body, headers, timeout_ms) {
115
118
  timeout: timeout_ms,
116
119
  };
117
120
 
118
- const req = https.request(opts, (res) => {
121
+ const req = transport.request(opts, (res) => {
119
122
  const chunks = [];
120
123
  res.on('data', chunk => chunks.push(chunk));
121
124
  res.on('end', () => {
@@ -131,6 +134,37 @@ function _http_post(url_str, body, headers, timeout_ms) {
131
134
  });
132
135
  }
133
136
 
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
+
134
168
  // ── Client ─────────────────────────────────────────────────────────────────────
135
169
 
136
170
  class BuiltWithClient {
@@ -140,6 +174,7 @@ class BuiltWithClient {
140
174
  }
141
175
  this._api_key = api_key;
142
176
  this._endpoint = options.endpoint || MCP_ENDPOINT;
177
+ this._payments_endpoint = options.payments_endpoint || PAYMENTS_ENDPOINT;
143
178
  this._max_retries = options.max_retries != null ? options.max_retries : MAX_RETRIES;
144
179
  this._timeout_ms = options.timeout_ms || 30000;
145
180
  }
@@ -236,6 +271,38 @@ class BuiltWithClient {
236
271
  return _err(last_error || new BuiltWithError('UNKNOWN_ERROR', 'Request failed', 0), mcp_tool);
237
272
  }
238
273
 
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
+
239
306
  // ── Public SDK methods ─────────────────────────────────────────────────────
240
307
 
241
308
  async domain_lookup_live(params) {
@@ -322,6 +389,34 @@ class BuiltWithClient {
322
389
  return this._request('social-api', { lookup });
323
390
  }
324
391
 
392
+ async vector_search(params) {
393
+ const { query, limit } = params || {};
394
+ _validate_string('query', query);
395
+ return this._request('vector-search', { query, ...(limit != null ? { limit } : {}) });
396
+ }
397
+
398
+ async payment_discovery() {
399
+ return this._payment_request('GET', '/v1/billing/api-discovery');
400
+ }
401
+
402
+ async payment_configuration() {
403
+ return this._payment_request('GET', '/v1/billing/api-configuration');
404
+ }
405
+
406
+ async payment_purchase(params) {
407
+ const { credits } = params || {};
408
+ if (credits === undefined || credits === null) {
409
+ throw new BuiltWithError('VALIDATION_ERROR', 'credits is required.', 0, null, 'Provide a credits value (minimum 2000).');
410
+ }
411
+ if (typeof credits !== 'number' || !Number.isInteger(credits)) {
412
+ throw new BuiltWithError('VALIDATION_ERROR', 'credits must be an integer.', 0, null, 'Provide a whole number of credits.');
413
+ }
414
+ if (credits < 2000) {
415
+ throw new BuiltWithError('VALIDATION_ERROR', 'credits must be at least 2000.', 0, null, 'Minimum purchase is 2000 credits.');
416
+ }
417
+ return this._payment_request('POST', '/v1/billing/api-purchase', { credits });
418
+ }
419
+
325
420
  // ── Prompt helpers ─────────────────────────────────────────────────────────
326
421
 
327
422
  prompt_analyze_tech_stack(params) {