@bisibility/sdk 0.6.1 → 0.7.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 +22 -0
- package/README.md +88 -65
- package/dist/api-version.d.ts +4 -0
- package/dist/api-version.d.ts.map +1 -0
- package/dist/api-version.js +4 -0
- package/dist/api-version.js.map +1 -0
- package/dist/client.d.ts +156 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +275 -10
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +10 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +14 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/public-id-contract.d.ts.map +1 -1
- package/dist/public-id-contract.js +3 -0
- package/dist/public-id-contract.js.map +1 -1
- package/dist/resources.d.ts +197 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +278 -0
- package/dist/resources.js.map +1 -0
- package/dist/types.d.ts +61 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.7.2 - 2026-08-02
|
|
6
|
+
|
|
7
|
+
- Added a separate `accessToken` configuration option for OAuth bearer tokens without applying
|
|
8
|
+
API key prefix validation.
|
|
9
|
+
|
|
10
|
+
## 0.7.1 - 2026-08-02
|
|
11
|
+
|
|
12
|
+
- Republished the 0.7.0 API surface after correcting release validation; runtime behavior is unchanged.
|
|
13
|
+
|
|
14
|
+
## 0.7.0 - 2026-08-02
|
|
15
|
+
|
|
16
|
+
- **Breaking for typed consumers:** `getHealth()`, `getLiveness()`, and `getReadiness()` now return
|
|
17
|
+
status-only responses; degraded health and readiness HTTP 503 responses return normally without
|
|
18
|
+
retries, while other endpoints retain 503 retries.
|
|
19
|
+
- Added resource-oriented namespaces such as `client.keywords.*`, `client.team.*`, and
|
|
20
|
+
`client.imports.*`; flat methods remain available as deprecated delegates until 1.0.
|
|
21
|
+
- Added typed Saved Keywords list, iterator, create, and delete operations with `svkw` public IDs.
|
|
22
|
+
- Added `Bisibility-API-Version` compatibility declarations, lazy server compatibility checks,
|
|
23
|
+
and `BisibilityApiVersionError` for unsupported newer server contracts.
|
|
24
|
+
|
|
3
25
|
## 0.6.1 - 2026-07-30
|
|
4
26
|
|
|
5
27
|
- Improved package metadata to describe the SDK's SEO rank-tracking, keyword, and ranking-history
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
> [API reference](https://bisibility.com/docs/api/overview) ·
|
|
9
9
|
> [Roadmap](https://bisibility.com/roadmap)
|
|
10
10
|
>
|
|
11
|
-
> **Status:** Published on npm as v0.
|
|
11
|
+
> **Status:** Published on npm as v0.6.1.
|
|
12
12
|
|
|
13
13
|
TypeScript SDK for the Bisibility REST API.
|
|
14
14
|
|
|
@@ -35,11 +35,11 @@ const bisibility = new BisibilityClient({
|
|
|
35
35
|
apiKey: process.env.BISIBILITY_API_KEY
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
const projects = await bisibility.
|
|
38
|
+
const projects = await bisibility.projects.list();
|
|
39
39
|
const projectId = projects.data[0]?.id;
|
|
40
40
|
|
|
41
41
|
if (projectId) {
|
|
42
|
-
const created = await bisibility.
|
|
42
|
+
const created = await bisibility.keywords.add(projectId, {
|
|
43
43
|
keywords: [
|
|
44
44
|
{
|
|
45
45
|
keyword: "rank tracker api",
|
|
@@ -51,7 +51,7 @@ if (projectId) {
|
|
|
51
51
|
|
|
52
52
|
const keywordId = created.results[0]?.keyword.id;
|
|
53
53
|
if (keywordId) {
|
|
54
|
-
const check = await bisibility.
|
|
54
|
+
const check = await bisibility.rankChecks.run(keywordId);
|
|
55
55
|
console.log(check.position, check.ranking_url);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -80,9 +80,18 @@ const bisibility = new BisibilityClient({
|
|
|
80
80
|
projectId: process.env.BISIBILITY_PROJECT_ID
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
const me = await bisibility.
|
|
84
|
-
const project = await bisibility.
|
|
85
|
-
await bisibility.
|
|
83
|
+
const me = await bisibility.account.get();
|
|
84
|
+
const project = await bisibility.projects.create({ domain: "example.com", name: "Example" });
|
|
85
|
+
await bisibility.apiKeys.create({ name: "CI" }, { projectId: project.id });
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
OAuth clients can pass their opaque bearer token as `accessToken`. It is mutually exclusive with
|
|
89
|
+
`apiKey` and does not use API key prefix validation:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
const bisibility = new BisibilityClient({
|
|
93
|
+
accessToken: oauth.accessToken,
|
|
94
|
+
});
|
|
86
95
|
```
|
|
87
96
|
|
|
88
97
|
A custom `fetch` implementation can be injected for older runtimes, proxies, or testing:
|
|
@@ -94,7 +103,8 @@ const bisibility = new BisibilityClient({
|
|
|
94
103
|
});
|
|
95
104
|
```
|
|
96
105
|
|
|
97
|
-
Protected methods send `Authorization: Bearer <
|
|
106
|
+
Protected methods send the configured `apiKey` or `accessToken` as `Authorization: Bearer <token>`.
|
|
107
|
+
Write methods accept an optional
|
|
98
108
|
`idempotencyKey` request option, which maps to the server `Idempotency-Key` header.
|
|
99
109
|
Requests set `redirect: "error"` so credentials are never forwarded through an HTTP redirect.
|
|
100
110
|
Custom `fetch` implementations should preserve that behavior.
|
|
@@ -112,7 +122,7 @@ up to 60 seconds.
|
|
|
112
122
|
Every method accepts per-request options:
|
|
113
123
|
|
|
114
124
|
```ts
|
|
115
|
-
await bisibility.
|
|
125
|
+
await bisibility.projects.list({
|
|
116
126
|
headers: { "X-Request-Id": "..." },
|
|
117
127
|
signal: controller.signal, // your own AbortSignal
|
|
118
128
|
timeout: 10_000 // ms; composed with `signal` when both are set
|
|
@@ -122,6 +132,15 @@ await bisibility.listProjects({
|
|
|
122
132
|
Without an explicit timeout or signal, every attempt has a 30-second timeout. Set `timeout: null`
|
|
123
133
|
on the client or an individual request to opt out.
|
|
124
134
|
|
|
135
|
+
### API version compatibility
|
|
136
|
+
|
|
137
|
+
The SDK declares `Bisibility-API-Version: v1` on every request. Before its first ordinary API
|
|
138
|
+
operation, each client lazily checks `/capabilities` once; calling `getCapabilities()` first
|
|
139
|
+
satisfies the same check without a duplicate request. A server that advertises `apiVersions` but
|
|
140
|
+
does not serve `v1` fails with `BisibilityApiVersionError` before the requested operation runs.
|
|
141
|
+
Older servers whose capabilities response has no `apiVersions` field remain compatible, and the
|
|
142
|
+
original request continues normally.
|
|
143
|
+
|
|
125
144
|
## Public resource IDs
|
|
126
145
|
|
|
127
146
|
Every resource identifier accepted or returned by the SDK uses public ID v3. The
|
|
@@ -139,38 +158,38 @@ Locations are identified by `location_key`; they do not expose a location ID.
|
|
|
139
158
|
Cloud import and export payloads use schema version 5 only. Pagination cursors are opaque SDK
|
|
140
159
|
values; v3 API cursors returned by the server must be passed back unchanged.
|
|
141
160
|
|
|
142
|
-
##
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
161
|
+
## Resource namespaces
|
|
162
|
+
|
|
163
|
+
The client groups operations by resource. Existing flat methods remain available as deprecated
|
|
164
|
+
compatibility delegates until 1.0.
|
|
165
|
+
|
|
166
|
+
| Namespace | Methods |
|
|
167
|
+
| - | - |
|
|
168
|
+
| `system` | `getHealth`, `getLiveness`, `getReadiness`, `getCapabilities`, `getOpenApi`, `getLlmsText` |
|
|
169
|
+
| `pricing` | `getRates`, `estimate` |
|
|
170
|
+
| `locations` | `search` |
|
|
171
|
+
| `account` | `get`, `update`, plus `tokens.list`, `tokens.create`, `tokens.revoke` |
|
|
172
|
+
| `projects` | `list`, `create`, `get`, `update`, `delete`, `getDefaults`, `updateDefaults` |
|
|
173
|
+
| `apiKeys` | `list`, `iterate`, `create`, `revoke` |
|
|
174
|
+
| `webhooks` | `list`, `iterate`, `create`, `update`, `delete` |
|
|
175
|
+
| `keywords` | `list`, `iterate`, `add`, `get`, `update`, `setTargetUrl`, `delete`, `bulkUpdate`, `match`, `research`, plus `suggestions.list`, `metrics.get` |
|
|
176
|
+
| `backlinks` | `analyze`, `extendSnapshot` |
|
|
177
|
+
| `rankChecks` | `list`, `iterate`, `run`, `getResult`, plus `history.export`, `history.iterate` |
|
|
178
|
+
| `sitemapMonitors` | `list`, `update` |
|
|
179
|
+
| `signals` | `list`, `iterate`, `create` |
|
|
180
|
+
| `analytics` | `overview.get`, `traffic.list`, `traffic.sync`, `searchPerformance.list` |
|
|
181
|
+
| `alertRules` | `list`, `iterate`, `create`, `update`, `delete` |
|
|
182
|
+
| `alerts` | `list`, `iterate`, `mute`, `markAllRead` |
|
|
183
|
+
| `notificationSettings` | `get`, `update` |
|
|
184
|
+
| `team` | `members.*` and `invites.*` |
|
|
185
|
+
| `providers` | `list`, `iterate`, `connect`, `test`, `updateSettings`, `setEnabled`, `setPriority`, `setPrimary`, `disconnect` |
|
|
186
|
+
| `savedViews` | `list`, `iterate`, `create`, `delete` |
|
|
187
|
+
| `competitors` | `list`, `iterate`, `add`, `remove` |
|
|
188
|
+
| `imports` | `runFromExport`, plus `compatibility.*`, `tokens.*`, `sessions.*` |
|
|
189
|
+
|
|
190
|
+
`apiKeys.list()` and `apiKeys.create()` use the current project selected by authentication. Pass
|
|
191
|
+
`{ projectId }` to select the explicit project route. A personal access token spanning multiple
|
|
192
|
+
projects must pass `projectId` because the top-level route cannot select a project unambiguously.
|
|
174
193
|
|
|
175
194
|
List methods return `{ data, meta }` with `meta.next_cursor`. Resource methods return the resource
|
|
176
195
|
object directly, matching the Bisibility API response shape.
|
|
@@ -179,7 +198,7 @@ Every cursor-paginated list has an `iterate*` counterpart that preserves filters
|
|
|
179
198
|
across all pages:
|
|
180
199
|
|
|
181
200
|
```ts
|
|
182
|
-
for await (const keyword of bisibility.
|
|
201
|
+
for await (const keyword of bisibility.keywords.iterate(projectId, { device: "desktop" })) {
|
|
183
202
|
console.log(keyword.text);
|
|
184
203
|
}
|
|
185
204
|
```
|
|
@@ -191,12 +210,12 @@ endpoints.
|
|
|
191
210
|
|
|
192
211
|
### Keyword research and metrics
|
|
193
212
|
|
|
194
|
-
`
|
|
213
|
+
`keywords.research` runs a paid, cached DataForSEO lookup for one seed. Select the research depth
|
|
195
214
|
up front with `resultLimit`; this endpoint does not use offset pagination. It requires API write
|
|
196
215
|
scope because a cache miss can spend the project's provider budget:
|
|
197
216
|
|
|
198
217
|
```ts
|
|
199
|
-
const research = await bisibility.
|
|
218
|
+
const research = await bisibility.keywords.research(projectId, {
|
|
200
219
|
seed: "rank tracker",
|
|
201
220
|
mode: "auto",
|
|
202
221
|
resultLimit: 300,
|
|
@@ -208,11 +227,11 @@ const research = await bisibility.researchKeywords(projectId, {
|
|
|
208
227
|
Set `estimateOnly: true` for a free cache-aware dry run before a cost-sensitive request. Source
|
|
209
228
|
diagnostics report `ok`, `failed`, or `skipped`, with a machine-readable reason when applicable.
|
|
210
229
|
|
|
211
|
-
`
|
|
230
|
+
`keywords.metrics.get` hydrates provider metrics for one to 700 keywords. Its input mirrors the API
|
|
212
231
|
request body, cached rows do not contribute to `cost_cents`, and API write scope is required:
|
|
213
232
|
|
|
214
233
|
```ts
|
|
215
|
-
const metrics = await bisibility.
|
|
234
|
+
const metrics = await bisibility.keywords.metrics.get(projectId, {
|
|
216
235
|
keywords: ["rank tracker", "seo api"],
|
|
217
236
|
include_clickstream: false,
|
|
218
237
|
estimate_only: true,
|
|
@@ -228,11 +247,11 @@ provider market does not supply them.
|
|
|
228
247
|
|
|
229
248
|
### Project defaults
|
|
230
249
|
|
|
231
|
-
`
|
|
250
|
+
`projects.updateDefaults(projectId, patch)` sends `PATCH /projects/{id}/defaults` and returns the
|
|
232
251
|
persisted `ProjectDefaults` (default market, schedule, and timezone for new keywords):
|
|
233
252
|
|
|
234
253
|
```ts
|
|
235
|
-
await bisibility.
|
|
254
|
+
await bisibility.projects.updateDefaults(projectId, {
|
|
236
255
|
country: "United States",
|
|
237
256
|
device: "desktop",
|
|
238
257
|
frequency: "daily"
|
|
@@ -241,35 +260,35 @@ await bisibility.updateProjectDefaults(projectId, {
|
|
|
241
260
|
|
|
242
261
|
### Asynchronous rank checks
|
|
243
262
|
|
|
244
|
-
`
|
|
263
|
+
`rankChecks.run` runs synchronously by default. Pass `async: true` to enqueue the check instead;
|
|
245
264
|
the server responds `202` with a `RankCheck` in `status: "running"` that you can poll via
|
|
246
265
|
`getRankCheckResult`:
|
|
247
266
|
|
|
248
267
|
```ts
|
|
249
|
-
const queued = await bisibility.
|
|
268
|
+
const queued = await bisibility.rankChecks.run(keywordId, undefined, { async: true });
|
|
250
269
|
// queued.status === "running"
|
|
251
|
-
const result = await bisibility.
|
|
270
|
+
const result = await bisibility.rankChecks.getResult(queued.id);
|
|
252
271
|
```
|
|
253
272
|
|
|
254
273
|
Failed checks carry `status: "failed"`, an `error` message, and provider fallback `attempts`.
|
|
255
274
|
|
|
256
275
|
### Signals
|
|
257
276
|
|
|
258
|
-
`
|
|
277
|
+
`signals.create` ingests a signal (`POST /signals`) into the project tied to your API key;
|
|
259
278
|
`source` must be `"deploy"`, `"cms"`, or `"api"`, and `type` follows the
|
|
260
279
|
`category.event` pattern (for example `deploy.completed`). `listSignals(projectId, options)`
|
|
261
280
|
pages through a project's signals newest first with optional `source`, `type`, `from`, and `to`
|
|
262
281
|
filters:
|
|
263
282
|
|
|
264
283
|
```ts
|
|
265
|
-
await bisibility.
|
|
284
|
+
await bisibility.signals.create({
|
|
266
285
|
source: "deploy",
|
|
267
286
|
type: "deploy.completed",
|
|
268
287
|
payload: { version: "1.2.3" }, // <= 8KB serialized
|
|
269
288
|
url: "https://example.com/releases/1"
|
|
270
289
|
});
|
|
271
290
|
|
|
272
|
-
const recent = await bisibility.
|
|
291
|
+
const recent = await bisibility.signals.list(projectId, {
|
|
273
292
|
source: "deploy",
|
|
274
293
|
from: "2026-07-01T00:00:00.000Z"
|
|
275
294
|
});
|
|
@@ -277,11 +296,11 @@ const recent = await bisibility.listSignals(projectId, {
|
|
|
277
296
|
|
|
278
297
|
### Public cost estimates
|
|
279
298
|
|
|
280
|
-
`
|
|
299
|
+
`pricing.getRates` and `pricing.estimate` are anonymous and work without an `apiKey`:
|
|
281
300
|
|
|
282
301
|
```ts
|
|
283
|
-
const rates = await bisibility.
|
|
284
|
-
const estimate = await bisibility.
|
|
302
|
+
const rates = await bisibility.pricing.getRates();
|
|
303
|
+
const estimate = await bisibility.pricing.estimate({
|
|
285
304
|
keywords: 250,
|
|
286
305
|
frequency: "daily",
|
|
287
306
|
provider: "dataforseo",
|
|
@@ -293,19 +312,23 @@ const estimate = await bisibility.getCostEstimate({
|
|
|
293
312
|
## Errors
|
|
294
313
|
|
|
295
314
|
All SDK errors extend `BisibilityError`; its concrete subclasses are `BisibilityApiError`,
|
|
296
|
-
`BisibilityConfigurationError`, `BisibilityNetworkError`, and
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
315
|
+
`BisibilityApiVersionError`, `BisibilityConfigurationError`, `BisibilityNetworkError`, and
|
|
316
|
+
`BisibilityResponseError`. `BisibilityApiVersionError` also extends `BisibilityApiError` and exposes
|
|
317
|
+
the declared version as `declaredApiVersion` plus the server advertisement as
|
|
318
|
+
`serverApiVersions`. The original RFC problem details body is available on API errors as
|
|
319
|
+
`error.problem`. API errors also provide `isRateLimit`, `isNotFound`, and `retryAfterSeconds`.
|
|
320
|
+
`error.headers` retains ordinary response headers while credential and cookie headers are removed
|
|
321
|
+
before the error is exposed to application logs.
|
|
301
322
|
|
|
302
323
|
```ts
|
|
303
|
-
import { BisibilityApiError } from "@bisibility/sdk";
|
|
324
|
+
import { BisibilityApiError, BisibilityApiVersionError } from "@bisibility/sdk";
|
|
304
325
|
|
|
305
326
|
try {
|
|
306
|
-
await bisibility.
|
|
327
|
+
await bisibility.keywords.get("kw_z9y8x7w6v5u4t3s2r1q0p9n8");
|
|
307
328
|
} catch (error) {
|
|
308
|
-
if (error instanceof
|
|
329
|
+
if (error instanceof BisibilityApiVersionError) {
|
|
330
|
+
console.error(error.declaredApiVersion, error.serverApiVersions);
|
|
331
|
+
} else if (error instanceof BisibilityApiError) {
|
|
309
332
|
console.error(error.status, error.problem?.detail);
|
|
310
333
|
}
|
|
311
334
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const BISIBILITY_API_VERSION = "v1";
|
|
2
|
+
export declare const BISIBILITY_API_VERSION_HEADER = "Bisibility-API-Version";
|
|
3
|
+
export declare const UNSUPPORTED_API_VERSION_PROBLEM_TYPE = "https://bisibility.com/problems/unsupported_api_version";
|
|
4
|
+
//# sourceMappingURL=api-version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-version.d.ts","sourceRoot":"","sources":["../src/api-version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,6BAA6B,2BAA2B,CAAC;AACtE,eAAO,MAAM,oCAAoC,4DACU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-version.js","sourceRoot":"","sources":["../src/api-version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,6BAA6B,GAAG,wBAAwB,CAAC;AACtE,MAAM,CAAC,MAAM,oCAAoC,GAC/C,yDAAyD,CAAC"}
|