@mentio-dev/cli 0.1.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 +15 -0
- package/dist/index.js +3823 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3823 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// src/index.ts
|
|
9
|
+
import { Command, Option } from "commander";
|
|
10
|
+
import { writeFileSync as writeFileSync2 } from "fs";
|
|
11
|
+
|
|
12
|
+
// package.json
|
|
13
|
+
var package_default = {
|
|
14
|
+
name: "@mentio-dev/cli",
|
|
15
|
+
version: "0.1.0",
|
|
16
|
+
description: "Command-line client for the Mentio API: one command per endpoint, plus watch and MCP helpers.",
|
|
17
|
+
license: "MIT",
|
|
18
|
+
homepage: "https://docs.mentio.dev/cli",
|
|
19
|
+
repository: {
|
|
20
|
+
type: "git",
|
|
21
|
+
url: "git+https://github.com/PauGuirao/mentions.git",
|
|
22
|
+
directory: "packages/cli"
|
|
23
|
+
},
|
|
24
|
+
bugs: {
|
|
25
|
+
url: "https://github.com/PauGuirao/mentions/issues"
|
|
26
|
+
},
|
|
27
|
+
keywords: [
|
|
28
|
+
"mentio",
|
|
29
|
+
"social listening",
|
|
30
|
+
"brand monitoring",
|
|
31
|
+
"cli",
|
|
32
|
+
"mcp"
|
|
33
|
+
],
|
|
34
|
+
type: "module",
|
|
35
|
+
bin: {
|
|
36
|
+
mentio: "./dist/index.js"
|
|
37
|
+
},
|
|
38
|
+
publishConfig: {
|
|
39
|
+
access: "public"
|
|
40
|
+
},
|
|
41
|
+
files: [
|
|
42
|
+
"dist",
|
|
43
|
+
"README.md"
|
|
44
|
+
],
|
|
45
|
+
engines: {
|
|
46
|
+
node: ">=22"
|
|
47
|
+
},
|
|
48
|
+
scripts: {
|
|
49
|
+
generate: "tsx scripts/generate-operations.ts",
|
|
50
|
+
build: "tsup",
|
|
51
|
+
dev: "tsx src/index.ts",
|
|
52
|
+
typecheck: "tsc --noEmit",
|
|
53
|
+
test: "vitest run",
|
|
54
|
+
prepublishOnly: "pnpm build"
|
|
55
|
+
},
|
|
56
|
+
dependencies: {
|
|
57
|
+
commander: "^15.0.0"
|
|
58
|
+
},
|
|
59
|
+
devDependencies: {
|
|
60
|
+
"@mentio-dev/sdk": "workspace:*",
|
|
61
|
+
"@types/node": "^22.15.0",
|
|
62
|
+
tsup: "^8.5.1",
|
|
63
|
+
tsx: "^4.23.1",
|
|
64
|
+
typescript: "^5.7.0",
|
|
65
|
+
vitest: "^3.0.0"
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// src/config.ts
|
|
70
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
71
|
+
import { homedir } from "os";
|
|
72
|
+
import { join } from "path";
|
|
73
|
+
var DEFAULT_API_URL = "https://api.mentio.dev";
|
|
74
|
+
function configDir(env = process.env) {
|
|
75
|
+
return env.MENTIO_CONFIG_DIR ?? join(homedir(), ".mentio");
|
|
76
|
+
}
|
|
77
|
+
function configPath(env = process.env) {
|
|
78
|
+
return join(configDir(env), "config.json");
|
|
79
|
+
}
|
|
80
|
+
function readConfig(env = process.env) {
|
|
81
|
+
const path = configPath(env);
|
|
82
|
+
if (!existsSync(path)) return {};
|
|
83
|
+
try {
|
|
84
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
85
|
+
if (parsed === null || typeof parsed !== "object") return {};
|
|
86
|
+
const record = parsed;
|
|
87
|
+
return {
|
|
88
|
+
apiKey: typeof record.apiKey === "string" ? record.apiKey : void 0,
|
|
89
|
+
apiUrl: typeof record.apiUrl === "string" ? record.apiUrl : void 0
|
|
90
|
+
};
|
|
91
|
+
} catch {
|
|
92
|
+
return {};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function writeConfig(patch, env = process.env) {
|
|
96
|
+
const current = readConfig(env);
|
|
97
|
+
const next = { ...current };
|
|
98
|
+
if (patch.apiKey === null) delete next.apiKey;
|
|
99
|
+
else if (patch.apiKey !== void 0) next.apiKey = patch.apiKey;
|
|
100
|
+
if (patch.apiUrl === null) delete next.apiUrl;
|
|
101
|
+
else if (patch.apiUrl !== void 0) next.apiUrl = patch.apiUrl;
|
|
102
|
+
const dir = configDir(env);
|
|
103
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
104
|
+
const path = configPath(env);
|
|
105
|
+
writeFileSync(path, `${JSON.stringify(next, null, 2)}
|
|
106
|
+
`, { mode: 384 });
|
|
107
|
+
chmodSync(path, 384);
|
|
108
|
+
return path;
|
|
109
|
+
}
|
|
110
|
+
function resolveSettings(flags, env = process.env) {
|
|
111
|
+
const file = readConfig(env);
|
|
112
|
+
const apiUrl = (flags.apiUrl ?? env.MENTIO_API_URL ?? file.apiUrl ?? DEFAULT_API_URL).replace(/\/+$/, "");
|
|
113
|
+
if (flags.apiKey) return { apiKey: flags.apiKey, apiUrl, source: "flag" };
|
|
114
|
+
if (env.MENTIO_API_KEY) return { apiKey: env.MENTIO_API_KEY, apiUrl, source: "env" };
|
|
115
|
+
if (file.apiKey) return { apiKey: file.apiKey, apiUrl, source: "file" };
|
|
116
|
+
return { apiKey: void 0, apiUrl, source: "none" };
|
|
117
|
+
}
|
|
118
|
+
function keyPrefix(key) {
|
|
119
|
+
const match = /^([a-z]+_[a-z]+_[a-z0-9]{4})/i.exec(key);
|
|
120
|
+
return match?.[1] ?? key.slice(0, 12);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/flags.ts
|
|
124
|
+
var UsageError = class extends Error {
|
|
125
|
+
constructor(message) {
|
|
126
|
+
super(message);
|
|
127
|
+
this.name = "UsageError";
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
function coerceScalar(field, raw, type) {
|
|
131
|
+
switch (type) {
|
|
132
|
+
case "integer":
|
|
133
|
+
case "number": {
|
|
134
|
+
const n = Number(raw);
|
|
135
|
+
if (raw.trim() === "" || !Number.isFinite(n)) throw new UsageError(`--${field.name} expects a number, got "${raw}"`);
|
|
136
|
+
if (type === "integer" && !Number.isInteger(n)) throw new UsageError(`--${field.name} expects a whole number, got "${raw}"`);
|
|
137
|
+
return n;
|
|
138
|
+
}
|
|
139
|
+
case "boolean":
|
|
140
|
+
if (raw === "true") return true;
|
|
141
|
+
if (raw === "false") return false;
|
|
142
|
+
throw new UsageError(`--${field.name} expects true or false, got "${raw}"`);
|
|
143
|
+
case "object": {
|
|
144
|
+
try {
|
|
145
|
+
const parsed = JSON.parse(raw);
|
|
146
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("not an object");
|
|
147
|
+
return parsed;
|
|
148
|
+
} catch {
|
|
149
|
+
throw new UsageError(`--${field.name} expects a JSON object, got "${raw}"`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
case "array":
|
|
153
|
+
case "string":
|
|
154
|
+
default:
|
|
155
|
+
return raw;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function coerce(field, raw) {
|
|
159
|
+
if (field.nullable && raw === "null") return null;
|
|
160
|
+
if (field.type === "array") {
|
|
161
|
+
if (field.in === "query") return raw;
|
|
162
|
+
const trimmed = raw.trim();
|
|
163
|
+
if (trimmed.startsWith("[")) {
|
|
164
|
+
try {
|
|
165
|
+
return JSON.parse(trimmed);
|
|
166
|
+
} catch {
|
|
167
|
+
throw new UsageError(`--${field.name} expects a comma-separated list or a JSON array`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const items = trimmed === "" ? [] : trimmed.split(",").map((v) => v.trim());
|
|
171
|
+
return items.map((item) => coerceScalar(field, item, field.items ?? "string"));
|
|
172
|
+
}
|
|
173
|
+
return coerceScalar(field, raw, field.type);
|
|
174
|
+
}
|
|
175
|
+
function flagHelp(field) {
|
|
176
|
+
const parts = [];
|
|
177
|
+
if (field.description) parts.push(field.description.replace(/\s+/g, " ").trim());
|
|
178
|
+
const hints = [];
|
|
179
|
+
if (field.type === "array") hints.push(field.enum ? `comma-separated: ${field.enum.join("|")}` : "comma-separated");
|
|
180
|
+
else if (field.type === "object") hints.push("JSON");
|
|
181
|
+
else if (field.type !== "string" && !field.enum) hints.push(field.type);
|
|
182
|
+
if (field.nullable) hints.push("null clears");
|
|
183
|
+
if (hints.length > 0) parts.push(`(${hints.join(", ")})`);
|
|
184
|
+
return parts.join(" ");
|
|
185
|
+
}
|
|
186
|
+
function buildRequest(op, positional, flags, jsonBody) {
|
|
187
|
+
const path = {};
|
|
188
|
+
const pathParams = op.params.filter((p) => p.in === "path");
|
|
189
|
+
pathParams.forEach((param, index) => {
|
|
190
|
+
const value = positional[index];
|
|
191
|
+
if (value === void 0 || value === "") throw new UsageError(`missing <${param.name}>`);
|
|
192
|
+
path[param.name] = value;
|
|
193
|
+
});
|
|
194
|
+
const query = {};
|
|
195
|
+
for (const param of op.params.filter((p) => p.in === "query")) {
|
|
196
|
+
const raw = flags[param.name];
|
|
197
|
+
if (raw === void 0) continue;
|
|
198
|
+
const value = coerce(param, String(raw));
|
|
199
|
+
if (value === null || typeof value === "object") continue;
|
|
200
|
+
query[param.name] = value;
|
|
201
|
+
}
|
|
202
|
+
let body;
|
|
203
|
+
if (op.body) {
|
|
204
|
+
body = {};
|
|
205
|
+
if (jsonBody !== void 0) {
|
|
206
|
+
let parsed;
|
|
207
|
+
try {
|
|
208
|
+
parsed = JSON.parse(jsonBody);
|
|
209
|
+
} catch {
|
|
210
|
+
throw new UsageError("--json is not valid JSON");
|
|
211
|
+
}
|
|
212
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) throw new UsageError("--json must be a JSON object");
|
|
213
|
+
body = parsed;
|
|
214
|
+
}
|
|
215
|
+
for (const field of op.body.fields) {
|
|
216
|
+
const raw = flags[field.name];
|
|
217
|
+
if (raw === void 0) continue;
|
|
218
|
+
body[field.name] = coerce(field, String(raw));
|
|
219
|
+
}
|
|
220
|
+
for (const field of op.body.fields) {
|
|
221
|
+
if (field.required && body[field.name] === void 0) throw new UsageError(`--${field.name} is required`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return { path, query, body };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// src/mcp.ts
|
|
228
|
+
var DEFAULT_MCP_URL = "https://mcp.mentio.dev/mcp";
|
|
229
|
+
function mcpConfig(kind, url, apiKey) {
|
|
230
|
+
const auth = `Bearer ${apiKey}`;
|
|
231
|
+
switch (kind) {
|
|
232
|
+
case "claude":
|
|
233
|
+
return `claude mcp add --transport http mentio ${url} --header "Authorization: ${auth}"`;
|
|
234
|
+
case "vscode":
|
|
235
|
+
return JSON.stringify({ servers: { mentio: { type: "http", url, headers: { Authorization: auth } } } }, null, 2);
|
|
236
|
+
case "cursor":
|
|
237
|
+
return JSON.stringify({ mcpServers: { mentio: { url, headers: { Authorization: auth } } } }, null, 2);
|
|
238
|
+
case "generic":
|
|
239
|
+
return JSON.stringify({ mcpServers: { mentio: { type: "http", url, headers: { Authorization: auth } } } }, null, 2);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// src/naming.ts
|
|
244
|
+
function commandName(op) {
|
|
245
|
+
const segments = op.path.replace(/^\/v1\//, "").split("/");
|
|
246
|
+
const noun = segments[0] ?? "";
|
|
247
|
+
if (noun === "health") return "system:health";
|
|
248
|
+
const rest = segments.slice(1);
|
|
249
|
+
const hasId = rest.some((s) => s.startsWith("{"));
|
|
250
|
+
const action = rest.find((s) => !s.startsWith("{"));
|
|
251
|
+
const method = op.method.toLowerCase();
|
|
252
|
+
let verb;
|
|
253
|
+
if (action !== void 0) {
|
|
254
|
+
verb = action === "export.csv" ? "export" : action;
|
|
255
|
+
} else if (method === "get" && !hasId) {
|
|
256
|
+
verb = op.operationId.startsWith("search") ? "search" : noun === "company" ? "get" : "list";
|
|
257
|
+
} else if (method === "post" && !hasId) {
|
|
258
|
+
verb = "create";
|
|
259
|
+
} else if (method === "get") {
|
|
260
|
+
verb = "get";
|
|
261
|
+
} else if (method === "patch") {
|
|
262
|
+
verb = "update";
|
|
263
|
+
} else if (method === "delete") {
|
|
264
|
+
verb = op.operationId.startsWith("revoke") ? "revoke" : "delete";
|
|
265
|
+
} else {
|
|
266
|
+
verb = method;
|
|
267
|
+
}
|
|
268
|
+
return `${noun}:${verb}`;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// src/generated/operations.ts
|
|
272
|
+
var OPERATIONS = [
|
|
273
|
+
{
|
|
274
|
+
"operationId": "getHealth",
|
|
275
|
+
"method": "GET",
|
|
276
|
+
"path": "/v1/health",
|
|
277
|
+
"summary": "getHealth",
|
|
278
|
+
"tag": "System",
|
|
279
|
+
"params": [],
|
|
280
|
+
"body": null,
|
|
281
|
+
"response": "json"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"operationId": "createKeyword",
|
|
285
|
+
"method": "POST",
|
|
286
|
+
"path": "/v1/keywords",
|
|
287
|
+
"summary": "Track a keyword",
|
|
288
|
+
"description": "Start tracking a word or phrase. Matching, classification and delivery begin on the next poll. Free workspaces track 2 keywords; a subscription raises that to 500.",
|
|
289
|
+
"tag": "Keywords",
|
|
290
|
+
"params": [],
|
|
291
|
+
"body": {
|
|
292
|
+
"fields": [
|
|
293
|
+
{
|
|
294
|
+
"name": "term",
|
|
295
|
+
"type": "string",
|
|
296
|
+
"description": "The word or phrase to track, matched case-insensitively as a phrase.",
|
|
297
|
+
"required": true,
|
|
298
|
+
"nullable": false
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
"name": "kind",
|
|
302
|
+
"type": "string",
|
|
303
|
+
"description": "brand: your own names. competitor: theirs. topic: the space. Drives share of voice and segments.",
|
|
304
|
+
"enum": [
|
|
305
|
+
"brand",
|
|
306
|
+
"competitor",
|
|
307
|
+
"topic"
|
|
308
|
+
],
|
|
309
|
+
"required": false,
|
|
310
|
+
"nullable": false
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"name": "platforms",
|
|
314
|
+
"type": "array",
|
|
315
|
+
"description": "Platforms to track it on; omit or null for every platform.",
|
|
316
|
+
"enum": [
|
|
317
|
+
"bluesky",
|
|
318
|
+
"hackernews",
|
|
319
|
+
"github",
|
|
320
|
+
"stackoverflow",
|
|
321
|
+
"devto",
|
|
322
|
+
"reddit",
|
|
323
|
+
"x",
|
|
324
|
+
"youtube",
|
|
325
|
+
"news",
|
|
326
|
+
"linkedin"
|
|
327
|
+
],
|
|
328
|
+
"required": false,
|
|
329
|
+
"nullable": true,
|
|
330
|
+
"items": "string"
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
},
|
|
334
|
+
"response": "json"
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
"operationId": "listKeywords",
|
|
338
|
+
"method": "GET",
|
|
339
|
+
"path": "/v1/keywords",
|
|
340
|
+
"summary": "List keywords",
|
|
341
|
+
"description": "Every keyword of the workspace, newest first, with its match stats and poll health.",
|
|
342
|
+
"tag": "Keywords",
|
|
343
|
+
"params": [],
|
|
344
|
+
"body": null,
|
|
345
|
+
"response": "json"
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"operationId": "getKeyword",
|
|
349
|
+
"method": "GET",
|
|
350
|
+
"path": "/v1/keywords/{id}",
|
|
351
|
+
"summary": "Get a keyword",
|
|
352
|
+
"tag": "Keywords",
|
|
353
|
+
"params": [
|
|
354
|
+
{
|
|
355
|
+
"name": "id",
|
|
356
|
+
"in": "path",
|
|
357
|
+
"type": "string",
|
|
358
|
+
"description": "Keyword id (kw_...).",
|
|
359
|
+
"required": true,
|
|
360
|
+
"nullable": false
|
|
361
|
+
}
|
|
362
|
+
],
|
|
363
|
+
"body": null,
|
|
364
|
+
"response": "json"
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"operationId": "updateKeyword",
|
|
368
|
+
"method": "PATCH",
|
|
369
|
+
"path": "/v1/keywords/{id}",
|
|
370
|
+
"summary": "Update a keyword",
|
|
371
|
+
"description": "Mute or unmute it, or change the platforms it is tracked on.",
|
|
372
|
+
"tag": "Keywords",
|
|
373
|
+
"params": [
|
|
374
|
+
{
|
|
375
|
+
"name": "id",
|
|
376
|
+
"in": "path",
|
|
377
|
+
"type": "string",
|
|
378
|
+
"description": "Keyword id (kw_...).",
|
|
379
|
+
"required": true,
|
|
380
|
+
"nullable": false
|
|
381
|
+
}
|
|
382
|
+
],
|
|
383
|
+
"body": {
|
|
384
|
+
"description": "Omitted fields are untouched.",
|
|
385
|
+
"fields": [
|
|
386
|
+
{
|
|
387
|
+
"name": "muted",
|
|
388
|
+
"type": "boolean",
|
|
389
|
+
"description": "A muted keyword stops polling and matching; its mentions stay.",
|
|
390
|
+
"required": false,
|
|
391
|
+
"nullable": false
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
"name": "platforms",
|
|
395
|
+
"type": "array",
|
|
396
|
+
"description": "Replaces the platform list; null means every platform.",
|
|
397
|
+
"enum": [
|
|
398
|
+
"bluesky",
|
|
399
|
+
"hackernews",
|
|
400
|
+
"github",
|
|
401
|
+
"stackoverflow",
|
|
402
|
+
"devto",
|
|
403
|
+
"reddit",
|
|
404
|
+
"x",
|
|
405
|
+
"youtube",
|
|
406
|
+
"news",
|
|
407
|
+
"linkedin"
|
|
408
|
+
],
|
|
409
|
+
"required": false,
|
|
410
|
+
"nullable": true,
|
|
411
|
+
"items": "string"
|
|
412
|
+
}
|
|
413
|
+
]
|
|
414
|
+
},
|
|
415
|
+
"response": "json"
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
"operationId": "deleteKeyword",
|
|
419
|
+
"method": "DELETE",
|
|
420
|
+
"path": "/v1/keywords/{id}",
|
|
421
|
+
"summary": "Delete a keyword",
|
|
422
|
+
"description": "Removes the keyword and its matches. Posts also matched by another keyword stay.",
|
|
423
|
+
"tag": "Keywords",
|
|
424
|
+
"params": [
|
|
425
|
+
{
|
|
426
|
+
"name": "id",
|
|
427
|
+
"in": "path",
|
|
428
|
+
"type": "string",
|
|
429
|
+
"description": "Keyword id (kw_...).",
|
|
430
|
+
"required": true,
|
|
431
|
+
"nullable": false
|
|
432
|
+
}
|
|
433
|
+
],
|
|
434
|
+
"body": null,
|
|
435
|
+
"response": "none"
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"operationId": "updateMention",
|
|
439
|
+
"method": "PATCH",
|
|
440
|
+
"path": "/v1/mentions/{id}",
|
|
441
|
+
"summary": "Update a mention",
|
|
442
|
+
"description": "The one write on a mention. Set status to ignored or done to handle it (open puts it back), assign it to a workspace member, snooze it out of the feed, or leave an internal note. Null clears a field; omitted fields are untouched. Delivery and billing never change.",
|
|
443
|
+
"tag": "Mentions",
|
|
444
|
+
"params": [
|
|
445
|
+
{
|
|
446
|
+
"name": "id",
|
|
447
|
+
"in": "path",
|
|
448
|
+
"type": "string",
|
|
449
|
+
"description": "Mention id (mm_...).",
|
|
450
|
+
"required": true,
|
|
451
|
+
"nullable": false
|
|
452
|
+
}
|
|
453
|
+
],
|
|
454
|
+
"body": {
|
|
455
|
+
"description": "Every field is optional; omitted fields are untouched.",
|
|
456
|
+
"fields": [
|
|
457
|
+
{
|
|
458
|
+
"name": "status",
|
|
459
|
+
"type": "string",
|
|
460
|
+
"description": "ignored or done to handle it; open to put it back.",
|
|
461
|
+
"enum": [
|
|
462
|
+
"open",
|
|
463
|
+
"ignored",
|
|
464
|
+
"done"
|
|
465
|
+
],
|
|
466
|
+
"required": false,
|
|
467
|
+
"nullable": false
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
"name": "assigneeId",
|
|
471
|
+
"type": "string",
|
|
472
|
+
"description": "A workspace member (user id), or null to unassign.",
|
|
473
|
+
"required": false,
|
|
474
|
+
"nullable": true
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
"name": "snoozedUntil",
|
|
478
|
+
"type": "integer",
|
|
479
|
+
"description": "ISO 8601 (or epoch ms) until which the mention leaves the feed; null wakes it.",
|
|
480
|
+
"required": false,
|
|
481
|
+
"nullable": true
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
"name": "note",
|
|
485
|
+
"type": "string",
|
|
486
|
+
"description": "Internal note; null or empty clears it.",
|
|
487
|
+
"required": false,
|
|
488
|
+
"nullable": true
|
|
489
|
+
}
|
|
490
|
+
]
|
|
491
|
+
},
|
|
492
|
+
"response": "json"
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
"operationId": "getMention",
|
|
496
|
+
"method": "GET",
|
|
497
|
+
"path": "/v1/mentions/{id}",
|
|
498
|
+
"summary": "Get a mention",
|
|
499
|
+
"description": "One mention by id, as it appears in the list: the post, its author with reach and your tags, the classification, the priority score and the triage fields. Ids belong to your organization; any other id is a 404.",
|
|
500
|
+
"tag": "Mentions",
|
|
501
|
+
"params": [
|
|
502
|
+
{
|
|
503
|
+
"name": "id",
|
|
504
|
+
"in": "path",
|
|
505
|
+
"type": "string",
|
|
506
|
+
"description": "Mention id (mm_...).",
|
|
507
|
+
"required": true,
|
|
508
|
+
"nullable": false
|
|
509
|
+
}
|
|
510
|
+
],
|
|
511
|
+
"body": null,
|
|
512
|
+
"response": "json"
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
"operationId": "searchMentions",
|
|
516
|
+
"method": "GET",
|
|
517
|
+
"path": "/v1/mentions",
|
|
518
|
+
"summary": "List mentions",
|
|
519
|
+
"description": "Mentions matched to your keywords, filtered and paginated. Default order is newest match first; sort=priority ranks by attention score. Page with nextCursor, passing the same filters and sort. A mention is one post matched to one keyword.",
|
|
520
|
+
"tag": "Mentions",
|
|
521
|
+
"params": [
|
|
522
|
+
{
|
|
523
|
+
"name": "keywordId",
|
|
524
|
+
"in": "query",
|
|
525
|
+
"type": "string",
|
|
526
|
+
"description": "Only matches of this keyword.",
|
|
527
|
+
"required": false,
|
|
528
|
+
"nullable": false
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
"name": "platform",
|
|
532
|
+
"in": "query",
|
|
533
|
+
"type": "string",
|
|
534
|
+
"description": "Only posts from this platform.",
|
|
535
|
+
"enum": [
|
|
536
|
+
"bluesky",
|
|
537
|
+
"hackernews",
|
|
538
|
+
"github",
|
|
539
|
+
"stackoverflow",
|
|
540
|
+
"devto",
|
|
541
|
+
"reddit",
|
|
542
|
+
"x",
|
|
543
|
+
"youtube",
|
|
544
|
+
"news",
|
|
545
|
+
"linkedin"
|
|
546
|
+
],
|
|
547
|
+
"required": false,
|
|
548
|
+
"nullable": false
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
"name": "status",
|
|
552
|
+
"in": "query",
|
|
553
|
+
"type": "string",
|
|
554
|
+
"description": "Only mentions in this status. Omit for every status.",
|
|
555
|
+
"enum": [
|
|
556
|
+
"open",
|
|
557
|
+
"ignored",
|
|
558
|
+
"done"
|
|
559
|
+
],
|
|
560
|
+
"required": false,
|
|
561
|
+
"nullable": false
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
"name": "relevant",
|
|
565
|
+
"in": "query",
|
|
566
|
+
"type": "boolean",
|
|
567
|
+
"description": "true: only mentions the classifier scored relevant; false: only the rest (unclassified included).",
|
|
568
|
+
"required": false,
|
|
569
|
+
"nullable": false
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
"name": "sentiment",
|
|
573
|
+
"in": "query",
|
|
574
|
+
"type": "string",
|
|
575
|
+
"description": "Only this sentiment.",
|
|
576
|
+
"enum": [
|
|
577
|
+
"positive",
|
|
578
|
+
"neutral",
|
|
579
|
+
"negative"
|
|
580
|
+
],
|
|
581
|
+
"required": false,
|
|
582
|
+
"nullable": false
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
"name": "intent",
|
|
586
|
+
"in": "query",
|
|
587
|
+
"type": "string",
|
|
588
|
+
"description": "Only mentions carrying this intent (buy_intent, question, complaint, praise, comparison).",
|
|
589
|
+
"required": false,
|
|
590
|
+
"nullable": false
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
"name": "personId",
|
|
594
|
+
"in": "query",
|
|
595
|
+
"type": "string",
|
|
596
|
+
"description": "Only this person (an id from /v1/people), merged accounts included. Implies includeMuted.",
|
|
597
|
+
"required": false,
|
|
598
|
+
"nullable": false
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
"name": "includeMuted",
|
|
602
|
+
"in": "query",
|
|
603
|
+
"type": "boolean",
|
|
604
|
+
"description": "true: include mentions by people you muted, hidden by default.",
|
|
605
|
+
"required": false,
|
|
606
|
+
"nullable": false
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
"name": "assigneeId",
|
|
610
|
+
"in": "query",
|
|
611
|
+
"type": "string",
|
|
612
|
+
"description": "Only mentions assigned to this workspace member (user id).",
|
|
613
|
+
"required": false,
|
|
614
|
+
"nullable": false
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
"name": "snoozed",
|
|
618
|
+
"in": "query",
|
|
619
|
+
"type": "boolean",
|
|
620
|
+
"description": "true: only mentions currently snoozed. Otherwise snoozed mentions stay out until they wake.",
|
|
621
|
+
"required": false,
|
|
622
|
+
"nullable": false
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
"name": "excludeAuthors",
|
|
626
|
+
"in": "query",
|
|
627
|
+
"type": "array",
|
|
628
|
+
"description": "Hide these authors: display names, handles or profile URLs. Repeatable, or one comma-separated value.",
|
|
629
|
+
"required": false,
|
|
630
|
+
"nullable": false
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
"name": "minRelevance",
|
|
634
|
+
"in": "query",
|
|
635
|
+
"type": "integer",
|
|
636
|
+
"description": "Only mentions scored at least this; unclassified ones are excluded.",
|
|
637
|
+
"required": false,
|
|
638
|
+
"nullable": false
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
"name": "minFollowers",
|
|
642
|
+
"in": "query",
|
|
643
|
+
"type": "integer",
|
|
644
|
+
"description": "Only authors with at least this many followers. Unknown reach never passes.",
|
|
645
|
+
"required": false,
|
|
646
|
+
"nullable": false
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
"name": "tags",
|
|
650
|
+
"in": "query",
|
|
651
|
+
"type": "array",
|
|
652
|
+
"description": "Only authors your workspace tagged with any of these (exact, case-sensitive). Repeatable, or comma-separated.",
|
|
653
|
+
"required": false,
|
|
654
|
+
"nullable": false
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
"name": "q",
|
|
658
|
+
"in": "query",
|
|
659
|
+
"type": "string",
|
|
660
|
+
"description": "Substring search in the post text.",
|
|
661
|
+
"required": false,
|
|
662
|
+
"nullable": false
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
"name": "since",
|
|
666
|
+
"in": "query",
|
|
667
|
+
"type": "integer",
|
|
668
|
+
"description": "Only posts published at or after this instant (ISO 8601, or epoch ms).",
|
|
669
|
+
"required": false,
|
|
670
|
+
"nullable": false
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
"name": "until",
|
|
674
|
+
"in": "query",
|
|
675
|
+
"type": "integer",
|
|
676
|
+
"description": "Only posts published at or before this instant (ISO 8601, or epoch ms).",
|
|
677
|
+
"required": false,
|
|
678
|
+
"nullable": false
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
"name": "sort",
|
|
682
|
+
"in": "query",
|
|
683
|
+
"type": "string",
|
|
684
|
+
"description": "newest: by match time, newest first. priority: by attention score, highest first. Cursors are specific to a sort.",
|
|
685
|
+
"enum": [
|
|
686
|
+
"newest",
|
|
687
|
+
"priority"
|
|
688
|
+
],
|
|
689
|
+
"required": false,
|
|
690
|
+
"nullable": false
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
"name": "cursor",
|
|
694
|
+
"in": "query",
|
|
695
|
+
"type": "string",
|
|
696
|
+
"description": "nextCursor from the previous page; pass the same filters and sort.",
|
|
697
|
+
"required": false,
|
|
698
|
+
"nullable": false
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
"name": "limit",
|
|
702
|
+
"in": "query",
|
|
703
|
+
"type": "integer",
|
|
704
|
+
"description": "Page size, 1 to 100.",
|
|
705
|
+
"required": false,
|
|
706
|
+
"nullable": false
|
|
707
|
+
}
|
|
708
|
+
],
|
|
709
|
+
"body": null,
|
|
710
|
+
"response": "json"
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
"operationId": "exportMentionsCsv",
|
|
714
|
+
"method": "GET",
|
|
715
|
+
"path": "/v1/mentions/export.csv",
|
|
716
|
+
"summary": "Export mentions as CSV",
|
|
717
|
+
"description": "The same mentions GET /v1/mentions would list for these filters, as CSV, newest published first: id, published_at, platform, keyword, author, author_url, author_followers, relevance, sentiment, intents (pipe-separated), status, relevant, delivered, url, text (first 1,000 characters). Capped at 10,000 rows; the X-Mentions-Truncated header says when the cap cut the list.",
|
|
718
|
+
"tag": "Mentions",
|
|
719
|
+
"params": [
|
|
720
|
+
{
|
|
721
|
+
"name": "keywordId",
|
|
722
|
+
"in": "query",
|
|
723
|
+
"type": "string",
|
|
724
|
+
"description": "Only matches of this keyword.",
|
|
725
|
+
"required": false,
|
|
726
|
+
"nullable": false
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
"name": "platform",
|
|
730
|
+
"in": "query",
|
|
731
|
+
"type": "string",
|
|
732
|
+
"description": "Only posts from this platform.",
|
|
733
|
+
"enum": [
|
|
734
|
+
"bluesky",
|
|
735
|
+
"hackernews",
|
|
736
|
+
"github",
|
|
737
|
+
"stackoverflow",
|
|
738
|
+
"devto",
|
|
739
|
+
"reddit",
|
|
740
|
+
"x",
|
|
741
|
+
"youtube",
|
|
742
|
+
"news",
|
|
743
|
+
"linkedin"
|
|
744
|
+
],
|
|
745
|
+
"required": false,
|
|
746
|
+
"nullable": false
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
"name": "status",
|
|
750
|
+
"in": "query",
|
|
751
|
+
"type": "string",
|
|
752
|
+
"description": "Only mentions in this status. Omit for every status.",
|
|
753
|
+
"enum": [
|
|
754
|
+
"open",
|
|
755
|
+
"ignored",
|
|
756
|
+
"done"
|
|
757
|
+
],
|
|
758
|
+
"required": false,
|
|
759
|
+
"nullable": false
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
"name": "relevant",
|
|
763
|
+
"in": "query",
|
|
764
|
+
"type": "boolean",
|
|
765
|
+
"description": "true: only mentions the classifier scored relevant; false: only the rest (unclassified included).",
|
|
766
|
+
"required": false,
|
|
767
|
+
"nullable": false
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
"name": "sentiment",
|
|
771
|
+
"in": "query",
|
|
772
|
+
"type": "string",
|
|
773
|
+
"description": "Only this sentiment.",
|
|
774
|
+
"enum": [
|
|
775
|
+
"positive",
|
|
776
|
+
"neutral",
|
|
777
|
+
"negative"
|
|
778
|
+
],
|
|
779
|
+
"required": false,
|
|
780
|
+
"nullable": false
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
"name": "intent",
|
|
784
|
+
"in": "query",
|
|
785
|
+
"type": "string",
|
|
786
|
+
"description": "Only mentions carrying this intent (buy_intent, question, complaint, praise, comparison).",
|
|
787
|
+
"required": false,
|
|
788
|
+
"nullable": false
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
"name": "personId",
|
|
792
|
+
"in": "query",
|
|
793
|
+
"type": "string",
|
|
794
|
+
"description": "Only this person (an id from /v1/people), merged accounts included. Implies includeMuted.",
|
|
795
|
+
"required": false,
|
|
796
|
+
"nullable": false
|
|
797
|
+
},
|
|
798
|
+
{
|
|
799
|
+
"name": "includeMuted",
|
|
800
|
+
"in": "query",
|
|
801
|
+
"type": "boolean",
|
|
802
|
+
"description": "true: include mentions by people you muted, hidden by default.",
|
|
803
|
+
"required": false,
|
|
804
|
+
"nullable": false
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
"name": "assigneeId",
|
|
808
|
+
"in": "query",
|
|
809
|
+
"type": "string",
|
|
810
|
+
"description": "Only mentions assigned to this workspace member (user id).",
|
|
811
|
+
"required": false,
|
|
812
|
+
"nullable": false
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
"name": "snoozed",
|
|
816
|
+
"in": "query",
|
|
817
|
+
"type": "boolean",
|
|
818
|
+
"description": "true: only mentions currently snoozed. Otherwise snoozed mentions stay out until they wake.",
|
|
819
|
+
"required": false,
|
|
820
|
+
"nullable": false
|
|
821
|
+
},
|
|
822
|
+
{
|
|
823
|
+
"name": "excludeAuthors",
|
|
824
|
+
"in": "query",
|
|
825
|
+
"type": "array",
|
|
826
|
+
"description": "Hide these authors: display names, handles or profile URLs. Repeatable, or one comma-separated value.",
|
|
827
|
+
"required": false,
|
|
828
|
+
"nullable": false
|
|
829
|
+
},
|
|
830
|
+
{
|
|
831
|
+
"name": "minRelevance",
|
|
832
|
+
"in": "query",
|
|
833
|
+
"type": "integer",
|
|
834
|
+
"description": "Only mentions scored at least this; unclassified ones are excluded.",
|
|
835
|
+
"required": false,
|
|
836
|
+
"nullable": false
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
"name": "minFollowers",
|
|
840
|
+
"in": "query",
|
|
841
|
+
"type": "integer",
|
|
842
|
+
"description": "Only authors with at least this many followers. Unknown reach never passes.",
|
|
843
|
+
"required": false,
|
|
844
|
+
"nullable": false
|
|
845
|
+
},
|
|
846
|
+
{
|
|
847
|
+
"name": "tags",
|
|
848
|
+
"in": "query",
|
|
849
|
+
"type": "array",
|
|
850
|
+
"description": "Only authors your workspace tagged with any of these (exact, case-sensitive). Repeatable, or comma-separated.",
|
|
851
|
+
"required": false,
|
|
852
|
+
"nullable": false
|
|
853
|
+
},
|
|
854
|
+
{
|
|
855
|
+
"name": "q",
|
|
856
|
+
"in": "query",
|
|
857
|
+
"type": "string",
|
|
858
|
+
"description": "Substring search in the post text.",
|
|
859
|
+
"required": false,
|
|
860
|
+
"nullable": false
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
"name": "since",
|
|
864
|
+
"in": "query",
|
|
865
|
+
"type": "integer",
|
|
866
|
+
"description": "Only posts published at or after this instant (ISO 8601, or epoch ms).",
|
|
867
|
+
"required": false,
|
|
868
|
+
"nullable": false
|
|
869
|
+
},
|
|
870
|
+
{
|
|
871
|
+
"name": "until",
|
|
872
|
+
"in": "query",
|
|
873
|
+
"type": "integer",
|
|
874
|
+
"description": "Only posts published at or before this instant (ISO 8601, or epoch ms).",
|
|
875
|
+
"required": false,
|
|
876
|
+
"nullable": false
|
|
877
|
+
}
|
|
878
|
+
],
|
|
879
|
+
"body": null,
|
|
880
|
+
"response": "csv"
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
"operationId": "exportPeopleCsv",
|
|
884
|
+
"method": "GET",
|
|
885
|
+
"path": "/v1/people/export.csv",
|
|
886
|
+
"summary": "Export people as CSV",
|
|
887
|
+
"description": "The same list as GET /v1/people (segmentId included) as CSV, one row per person with their contact columns: handle, followers, email, website, company, location, tags. Capped at 5,000 people.",
|
|
888
|
+
"tag": "People",
|
|
889
|
+
"params": [
|
|
890
|
+
{
|
|
891
|
+
"name": "platform",
|
|
892
|
+
"in": "query",
|
|
893
|
+
"type": "string",
|
|
894
|
+
"description": "People with an account on this platform.",
|
|
895
|
+
"enum": [
|
|
896
|
+
"bluesky",
|
|
897
|
+
"hackernews",
|
|
898
|
+
"github",
|
|
899
|
+
"stackoverflow",
|
|
900
|
+
"devto",
|
|
901
|
+
"reddit",
|
|
902
|
+
"x",
|
|
903
|
+
"youtube",
|
|
904
|
+
"news",
|
|
905
|
+
"linkedin"
|
|
906
|
+
],
|
|
907
|
+
"required": false,
|
|
908
|
+
"nullable": false
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
"name": "q",
|
|
912
|
+
"in": "query",
|
|
913
|
+
"type": "string",
|
|
914
|
+
"description": "Matches the display name or the profile handle or URL, case-insensitively.",
|
|
915
|
+
"required": false,
|
|
916
|
+
"nullable": false
|
|
917
|
+
},
|
|
918
|
+
{
|
|
919
|
+
"name": "tag",
|
|
920
|
+
"in": "query",
|
|
921
|
+
"type": "string",
|
|
922
|
+
"description": "Only people carrying this tag (exact, case-sensitive).",
|
|
923
|
+
"required": false,
|
|
924
|
+
"nullable": false
|
|
925
|
+
},
|
|
926
|
+
{
|
|
927
|
+
"name": "muted",
|
|
928
|
+
"in": "query",
|
|
929
|
+
"type": "boolean",
|
|
930
|
+
"description": "true: only muted people; false: only unmuted; omitted: everyone.",
|
|
931
|
+
"required": false,
|
|
932
|
+
"nullable": false
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
"name": "since",
|
|
936
|
+
"in": "query",
|
|
937
|
+
"type": "integer",
|
|
938
|
+
"description": "Only people whose first matched mention is at or after this instant (ISO 8601, or epoch ms).",
|
|
939
|
+
"required": false,
|
|
940
|
+
"nullable": false
|
|
941
|
+
},
|
|
942
|
+
{
|
|
943
|
+
"name": "segmentId",
|
|
944
|
+
"in": "query",
|
|
945
|
+
"type": "string",
|
|
946
|
+
"description": "A saved segment applied on top of every other filter here. Unknown id: 404.",
|
|
947
|
+
"required": false,
|
|
948
|
+
"nullable": false
|
|
949
|
+
},
|
|
950
|
+
{
|
|
951
|
+
"name": "platforms",
|
|
952
|
+
"in": "query",
|
|
953
|
+
"type": "array",
|
|
954
|
+
"description": "People with an account on any of these platforms. Repeatable, or comma-separated.",
|
|
955
|
+
"enum": [
|
|
956
|
+
"bluesky",
|
|
957
|
+
"hackernews",
|
|
958
|
+
"github",
|
|
959
|
+
"stackoverflow",
|
|
960
|
+
"devto",
|
|
961
|
+
"reddit",
|
|
962
|
+
"x",
|
|
963
|
+
"youtube",
|
|
964
|
+
"news",
|
|
965
|
+
"linkedin"
|
|
966
|
+
],
|
|
967
|
+
"required": false,
|
|
968
|
+
"nullable": false
|
|
969
|
+
},
|
|
970
|
+
{
|
|
971
|
+
"name": "tags",
|
|
972
|
+
"in": "query",
|
|
973
|
+
"type": "array",
|
|
974
|
+
"description": "People carrying any of these tags. Repeatable, or comma-separated.",
|
|
975
|
+
"required": false,
|
|
976
|
+
"nullable": false
|
|
977
|
+
},
|
|
978
|
+
{
|
|
979
|
+
"name": "minFollowers",
|
|
980
|
+
"in": "query",
|
|
981
|
+
"type": "integer",
|
|
982
|
+
"description": "At least this many followers. Unknown reach never matches.",
|
|
983
|
+
"required": false,
|
|
984
|
+
"nullable": false
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
"name": "maxFollowers",
|
|
988
|
+
"in": "query",
|
|
989
|
+
"type": "integer",
|
|
990
|
+
"description": "At most this many followers.",
|
|
991
|
+
"required": false,
|
|
992
|
+
"nullable": false
|
|
993
|
+
},
|
|
994
|
+
{
|
|
995
|
+
"name": "minMentions",
|
|
996
|
+
"in": "query",
|
|
997
|
+
"type": "integer",
|
|
998
|
+
"description": "At least this many matched mentions.",
|
|
999
|
+
"required": false,
|
|
1000
|
+
"nullable": false
|
|
1001
|
+
},
|
|
1002
|
+
{
|
|
1003
|
+
"name": "minNegative",
|
|
1004
|
+
"in": "query",
|
|
1005
|
+
"type": "integer",
|
|
1006
|
+
"description": "At least this many negative mentions.",
|
|
1007
|
+
"required": false,
|
|
1008
|
+
"nullable": false
|
|
1009
|
+
},
|
|
1010
|
+
{
|
|
1011
|
+
"name": "intents",
|
|
1012
|
+
"in": "query",
|
|
1013
|
+
"type": "array",
|
|
1014
|
+
"description": "At least one mention carrying any of these intents.",
|
|
1015
|
+
"required": false,
|
|
1016
|
+
"nullable": false
|
|
1017
|
+
},
|
|
1018
|
+
{
|
|
1019
|
+
"name": "keywordKinds",
|
|
1020
|
+
"in": "query",
|
|
1021
|
+
"type": "array",
|
|
1022
|
+
"description": "Mentioned a keyword of any of these kinds.",
|
|
1023
|
+
"enum": [
|
|
1024
|
+
"brand",
|
|
1025
|
+
"competitor",
|
|
1026
|
+
"topic"
|
|
1027
|
+
],
|
|
1028
|
+
"required": false,
|
|
1029
|
+
"nullable": false
|
|
1030
|
+
},
|
|
1031
|
+
{
|
|
1032
|
+
"name": "neverKeywordKinds",
|
|
1033
|
+
"in": "query",
|
|
1034
|
+
"type": "array",
|
|
1035
|
+
"description": "Never mentioned a keyword of these kinds.",
|
|
1036
|
+
"enum": [
|
|
1037
|
+
"brand",
|
|
1038
|
+
"competitor",
|
|
1039
|
+
"topic"
|
|
1040
|
+
],
|
|
1041
|
+
"required": false,
|
|
1042
|
+
"nullable": false
|
|
1043
|
+
},
|
|
1044
|
+
{
|
|
1045
|
+
"name": "newSinceDays",
|
|
1046
|
+
"in": "query",
|
|
1047
|
+
"type": "integer",
|
|
1048
|
+
"description": "First seen within this many days.",
|
|
1049
|
+
"required": false,
|
|
1050
|
+
"nullable": false
|
|
1051
|
+
},
|
|
1052
|
+
{
|
|
1053
|
+
"name": "sort",
|
|
1054
|
+
"in": "query",
|
|
1055
|
+
"type": "string",
|
|
1056
|
+
"description": "mentions: most matches first. recent: last seen first. reach: most followers first, unknown last. new: first seen most recently first.",
|
|
1057
|
+
"enum": [
|
|
1058
|
+
"mentions",
|
|
1059
|
+
"recent",
|
|
1060
|
+
"reach",
|
|
1061
|
+
"new"
|
|
1062
|
+
],
|
|
1063
|
+
"required": false,
|
|
1064
|
+
"nullable": false
|
|
1065
|
+
}
|
|
1066
|
+
],
|
|
1067
|
+
"body": null,
|
|
1068
|
+
"response": "csv"
|
|
1069
|
+
},
|
|
1070
|
+
{
|
|
1071
|
+
"operationId": "listPeople",
|
|
1072
|
+
"method": "GET",
|
|
1073
|
+
"path": "/v1/people",
|
|
1074
|
+
"summary": "List people",
|
|
1075
|
+
"description": "The people behind your mentions: one row per person, with their accounts, reach, public profile, per-workspace stats and your annotations. Filter by platform, tag, follower range, mention counts, intents seen, keyword kinds mentioned or never mentioned, or a saved segment. Offset-paginated with a total.",
|
|
1076
|
+
"tag": "People",
|
|
1077
|
+
"params": [
|
|
1078
|
+
{
|
|
1079
|
+
"name": "platform",
|
|
1080
|
+
"in": "query",
|
|
1081
|
+
"type": "string",
|
|
1082
|
+
"description": "People with an account on this platform.",
|
|
1083
|
+
"enum": [
|
|
1084
|
+
"bluesky",
|
|
1085
|
+
"hackernews",
|
|
1086
|
+
"github",
|
|
1087
|
+
"stackoverflow",
|
|
1088
|
+
"devto",
|
|
1089
|
+
"reddit",
|
|
1090
|
+
"x",
|
|
1091
|
+
"youtube",
|
|
1092
|
+
"news",
|
|
1093
|
+
"linkedin"
|
|
1094
|
+
],
|
|
1095
|
+
"required": false,
|
|
1096
|
+
"nullable": false
|
|
1097
|
+
},
|
|
1098
|
+
{
|
|
1099
|
+
"name": "q",
|
|
1100
|
+
"in": "query",
|
|
1101
|
+
"type": "string",
|
|
1102
|
+
"description": "Matches the display name or the profile handle or URL, case-insensitively.",
|
|
1103
|
+
"required": false,
|
|
1104
|
+
"nullable": false
|
|
1105
|
+
},
|
|
1106
|
+
{
|
|
1107
|
+
"name": "tag",
|
|
1108
|
+
"in": "query",
|
|
1109
|
+
"type": "string",
|
|
1110
|
+
"description": "Only people carrying this tag (exact, case-sensitive).",
|
|
1111
|
+
"required": false,
|
|
1112
|
+
"nullable": false
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
"name": "muted",
|
|
1116
|
+
"in": "query",
|
|
1117
|
+
"type": "boolean",
|
|
1118
|
+
"description": "true: only muted people; false: only unmuted; omitted: everyone.",
|
|
1119
|
+
"required": false,
|
|
1120
|
+
"nullable": false
|
|
1121
|
+
},
|
|
1122
|
+
{
|
|
1123
|
+
"name": "since",
|
|
1124
|
+
"in": "query",
|
|
1125
|
+
"type": "integer",
|
|
1126
|
+
"description": "Only people whose first matched mention is at or after this instant (ISO 8601, or epoch ms).",
|
|
1127
|
+
"required": false,
|
|
1128
|
+
"nullable": false
|
|
1129
|
+
},
|
|
1130
|
+
{
|
|
1131
|
+
"name": "segmentId",
|
|
1132
|
+
"in": "query",
|
|
1133
|
+
"type": "string",
|
|
1134
|
+
"description": "A saved segment applied on top of every other filter here. Unknown id: 404.",
|
|
1135
|
+
"required": false,
|
|
1136
|
+
"nullable": false
|
|
1137
|
+
},
|
|
1138
|
+
{
|
|
1139
|
+
"name": "platforms",
|
|
1140
|
+
"in": "query",
|
|
1141
|
+
"type": "array",
|
|
1142
|
+
"description": "People with an account on any of these platforms. Repeatable, or comma-separated.",
|
|
1143
|
+
"enum": [
|
|
1144
|
+
"bluesky",
|
|
1145
|
+
"hackernews",
|
|
1146
|
+
"github",
|
|
1147
|
+
"stackoverflow",
|
|
1148
|
+
"devto",
|
|
1149
|
+
"reddit",
|
|
1150
|
+
"x",
|
|
1151
|
+
"youtube",
|
|
1152
|
+
"news",
|
|
1153
|
+
"linkedin"
|
|
1154
|
+
],
|
|
1155
|
+
"required": false,
|
|
1156
|
+
"nullable": false
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
"name": "tags",
|
|
1160
|
+
"in": "query",
|
|
1161
|
+
"type": "array",
|
|
1162
|
+
"description": "People carrying any of these tags. Repeatable, or comma-separated.",
|
|
1163
|
+
"required": false,
|
|
1164
|
+
"nullable": false
|
|
1165
|
+
},
|
|
1166
|
+
{
|
|
1167
|
+
"name": "minFollowers",
|
|
1168
|
+
"in": "query",
|
|
1169
|
+
"type": "integer",
|
|
1170
|
+
"description": "At least this many followers. Unknown reach never matches.",
|
|
1171
|
+
"required": false,
|
|
1172
|
+
"nullable": false
|
|
1173
|
+
},
|
|
1174
|
+
{
|
|
1175
|
+
"name": "maxFollowers",
|
|
1176
|
+
"in": "query",
|
|
1177
|
+
"type": "integer",
|
|
1178
|
+
"description": "At most this many followers.",
|
|
1179
|
+
"required": false,
|
|
1180
|
+
"nullable": false
|
|
1181
|
+
},
|
|
1182
|
+
{
|
|
1183
|
+
"name": "minMentions",
|
|
1184
|
+
"in": "query",
|
|
1185
|
+
"type": "integer",
|
|
1186
|
+
"description": "At least this many matched mentions.",
|
|
1187
|
+
"required": false,
|
|
1188
|
+
"nullable": false
|
|
1189
|
+
},
|
|
1190
|
+
{
|
|
1191
|
+
"name": "minNegative",
|
|
1192
|
+
"in": "query",
|
|
1193
|
+
"type": "integer",
|
|
1194
|
+
"description": "At least this many negative mentions.",
|
|
1195
|
+
"required": false,
|
|
1196
|
+
"nullable": false
|
|
1197
|
+
},
|
|
1198
|
+
{
|
|
1199
|
+
"name": "intents",
|
|
1200
|
+
"in": "query",
|
|
1201
|
+
"type": "array",
|
|
1202
|
+
"description": "At least one mention carrying any of these intents.",
|
|
1203
|
+
"required": false,
|
|
1204
|
+
"nullable": false
|
|
1205
|
+
},
|
|
1206
|
+
{
|
|
1207
|
+
"name": "keywordKinds",
|
|
1208
|
+
"in": "query",
|
|
1209
|
+
"type": "array",
|
|
1210
|
+
"description": "Mentioned a keyword of any of these kinds.",
|
|
1211
|
+
"enum": [
|
|
1212
|
+
"brand",
|
|
1213
|
+
"competitor",
|
|
1214
|
+
"topic"
|
|
1215
|
+
],
|
|
1216
|
+
"required": false,
|
|
1217
|
+
"nullable": false
|
|
1218
|
+
},
|
|
1219
|
+
{
|
|
1220
|
+
"name": "neverKeywordKinds",
|
|
1221
|
+
"in": "query",
|
|
1222
|
+
"type": "array",
|
|
1223
|
+
"description": "Never mentioned a keyword of these kinds.",
|
|
1224
|
+
"enum": [
|
|
1225
|
+
"brand",
|
|
1226
|
+
"competitor",
|
|
1227
|
+
"topic"
|
|
1228
|
+
],
|
|
1229
|
+
"required": false,
|
|
1230
|
+
"nullable": false
|
|
1231
|
+
},
|
|
1232
|
+
{
|
|
1233
|
+
"name": "newSinceDays",
|
|
1234
|
+
"in": "query",
|
|
1235
|
+
"type": "integer",
|
|
1236
|
+
"description": "First seen within this many days.",
|
|
1237
|
+
"required": false,
|
|
1238
|
+
"nullable": false
|
|
1239
|
+
},
|
|
1240
|
+
{
|
|
1241
|
+
"name": "sort",
|
|
1242
|
+
"in": "query",
|
|
1243
|
+
"type": "string",
|
|
1244
|
+
"description": "mentions: most matches first. recent: last seen first. reach: most followers first, unknown last. new: first seen most recently first.",
|
|
1245
|
+
"enum": [
|
|
1246
|
+
"mentions",
|
|
1247
|
+
"recent",
|
|
1248
|
+
"reach",
|
|
1249
|
+
"new"
|
|
1250
|
+
],
|
|
1251
|
+
"required": false,
|
|
1252
|
+
"nullable": false
|
|
1253
|
+
},
|
|
1254
|
+
{
|
|
1255
|
+
"name": "limit",
|
|
1256
|
+
"in": "query",
|
|
1257
|
+
"type": "integer",
|
|
1258
|
+
"description": "Page size, 1 to 100.",
|
|
1259
|
+
"required": false,
|
|
1260
|
+
"nullable": false
|
|
1261
|
+
},
|
|
1262
|
+
{
|
|
1263
|
+
"name": "offset",
|
|
1264
|
+
"in": "query",
|
|
1265
|
+
"type": "integer",
|
|
1266
|
+
"description": "Skip this many people. Offset paging: a grouped read over hundreds of people, not a stream.",
|
|
1267
|
+
"required": false,
|
|
1268
|
+
"nullable": false
|
|
1269
|
+
}
|
|
1270
|
+
],
|
|
1271
|
+
"body": null,
|
|
1272
|
+
"response": "json"
|
|
1273
|
+
},
|
|
1274
|
+
{
|
|
1275
|
+
"operationId": "getPerson",
|
|
1276
|
+
"method": "GET",
|
|
1277
|
+
"path": "/v1/people/{id}",
|
|
1278
|
+
"summary": "Get a person",
|
|
1279
|
+
"description": "One person as your workspace sees them. An account merged into someone resolves to that person.",
|
|
1280
|
+
"tag": "People",
|
|
1281
|
+
"params": [
|
|
1282
|
+
{
|
|
1283
|
+
"name": "id",
|
|
1284
|
+
"in": "path",
|
|
1285
|
+
"type": "string",
|
|
1286
|
+
"description": "Person id (aut_...).",
|
|
1287
|
+
"required": true,
|
|
1288
|
+
"nullable": false
|
|
1289
|
+
}
|
|
1290
|
+
],
|
|
1291
|
+
"body": null,
|
|
1292
|
+
"response": "json"
|
|
1293
|
+
},
|
|
1294
|
+
{
|
|
1295
|
+
"operationId": "updatePerson",
|
|
1296
|
+
"method": "PATCH",
|
|
1297
|
+
"path": "/v1/people/{id}",
|
|
1298
|
+
"summary": "Update your annotations on a person",
|
|
1299
|
+
"description": "Tags, notes and mute, for your workspace only. Mute hides their posts from your feed and every channel; ingest and billing never change.",
|
|
1300
|
+
"tag": "People",
|
|
1301
|
+
"params": [
|
|
1302
|
+
{
|
|
1303
|
+
"name": "id",
|
|
1304
|
+
"in": "path",
|
|
1305
|
+
"type": "string",
|
|
1306
|
+
"description": "Person id (aut_...).",
|
|
1307
|
+
"required": true,
|
|
1308
|
+
"nullable": false
|
|
1309
|
+
}
|
|
1310
|
+
],
|
|
1311
|
+
"body": {
|
|
1312
|
+
"description": "Omitted fields are untouched.",
|
|
1313
|
+
"fields": [
|
|
1314
|
+
{
|
|
1315
|
+
"name": "tags",
|
|
1316
|
+
"type": "array",
|
|
1317
|
+
"description": "Replaces the whole list.",
|
|
1318
|
+
"required": false,
|
|
1319
|
+
"nullable": false,
|
|
1320
|
+
"items": "string"
|
|
1321
|
+
},
|
|
1322
|
+
{
|
|
1323
|
+
"name": "notes",
|
|
1324
|
+
"type": "string",
|
|
1325
|
+
"required": false,
|
|
1326
|
+
"nullable": false
|
|
1327
|
+
},
|
|
1328
|
+
{
|
|
1329
|
+
"name": "muted",
|
|
1330
|
+
"type": "boolean",
|
|
1331
|
+
"required": false,
|
|
1332
|
+
"nullable": false
|
|
1333
|
+
}
|
|
1334
|
+
]
|
|
1335
|
+
},
|
|
1336
|
+
"response": "json"
|
|
1337
|
+
},
|
|
1338
|
+
{
|
|
1339
|
+
"operationId": "mergePeople",
|
|
1340
|
+
"method": "POST",
|
|
1341
|
+
"path": "/v1/people/{id}/merge",
|
|
1342
|
+
"summary": "Merge an account into a person",
|
|
1343
|
+
"description": "Declare that this account and another person are the same human, for your workspace only. Their mentions, tags and notes combine under the person named by `into`.",
|
|
1344
|
+
"tag": "People",
|
|
1345
|
+
"params": [
|
|
1346
|
+
{
|
|
1347
|
+
"name": "id",
|
|
1348
|
+
"in": "path",
|
|
1349
|
+
"type": "string",
|
|
1350
|
+
"description": "Person id (aut_...).",
|
|
1351
|
+
"required": true,
|
|
1352
|
+
"nullable": false
|
|
1353
|
+
}
|
|
1354
|
+
],
|
|
1355
|
+
"body": {
|
|
1356
|
+
"fields": [
|
|
1357
|
+
{
|
|
1358
|
+
"name": "into",
|
|
1359
|
+
"type": "string",
|
|
1360
|
+
"description": "The person to fold this account into (their id).",
|
|
1361
|
+
"required": true,
|
|
1362
|
+
"nullable": false
|
|
1363
|
+
}
|
|
1364
|
+
]
|
|
1365
|
+
},
|
|
1366
|
+
"response": "json"
|
|
1367
|
+
},
|
|
1368
|
+
{
|
|
1369
|
+
"operationId": "splitPerson",
|
|
1370
|
+
"method": "POST",
|
|
1371
|
+
"path": "/v1/people/{id}/split",
|
|
1372
|
+
"summary": "Undo a merge",
|
|
1373
|
+
"description": "The account becomes its own person again.",
|
|
1374
|
+
"tag": "People",
|
|
1375
|
+
"params": [
|
|
1376
|
+
{
|
|
1377
|
+
"name": "id",
|
|
1378
|
+
"in": "path",
|
|
1379
|
+
"type": "string",
|
|
1380
|
+
"description": "Person id (aut_...).",
|
|
1381
|
+
"required": true,
|
|
1382
|
+
"nullable": false
|
|
1383
|
+
}
|
|
1384
|
+
],
|
|
1385
|
+
"body": null,
|
|
1386
|
+
"response": "json"
|
|
1387
|
+
},
|
|
1388
|
+
{
|
|
1389
|
+
"operationId": "listSegments",
|
|
1390
|
+
"method": "GET",
|
|
1391
|
+
"path": "/v1/segments",
|
|
1392
|
+
"summary": "List segments",
|
|
1393
|
+
"description": "Your saved segments, each with the number of people in it right now (segments are evaluated on every read, never materialized), plus presets you can save as a starting point. Pass a segment id to GET /v1/people to list its members.",
|
|
1394
|
+
"tag": "Segments",
|
|
1395
|
+
"params": [],
|
|
1396
|
+
"body": null,
|
|
1397
|
+
"response": "json"
|
|
1398
|
+
},
|
|
1399
|
+
{
|
|
1400
|
+
"operationId": "createSegment",
|
|
1401
|
+
"method": "POST",
|
|
1402
|
+
"path": "/v1/segments",
|
|
1403
|
+
"summary": "Create a segment",
|
|
1404
|
+
"tag": "Segments",
|
|
1405
|
+
"params": [],
|
|
1406
|
+
"body": {
|
|
1407
|
+
"fields": [
|
|
1408
|
+
{
|
|
1409
|
+
"name": "name",
|
|
1410
|
+
"type": "string",
|
|
1411
|
+
"required": true,
|
|
1412
|
+
"nullable": false
|
|
1413
|
+
},
|
|
1414
|
+
{
|
|
1415
|
+
"name": "description",
|
|
1416
|
+
"type": "string",
|
|
1417
|
+
"required": false,
|
|
1418
|
+
"nullable": false
|
|
1419
|
+
},
|
|
1420
|
+
{
|
|
1421
|
+
"name": "filter",
|
|
1422
|
+
"type": "object",
|
|
1423
|
+
"required": false,
|
|
1424
|
+
"nullable": false
|
|
1425
|
+
}
|
|
1426
|
+
]
|
|
1427
|
+
},
|
|
1428
|
+
"response": "json"
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
"operationId": "getSegment",
|
|
1432
|
+
"method": "GET",
|
|
1433
|
+
"path": "/v1/segments/{id}",
|
|
1434
|
+
"summary": "Get a segment",
|
|
1435
|
+
"tag": "Segments",
|
|
1436
|
+
"params": [
|
|
1437
|
+
{
|
|
1438
|
+
"name": "id",
|
|
1439
|
+
"in": "path",
|
|
1440
|
+
"type": "string",
|
|
1441
|
+
"description": "Segment id (seg_...).",
|
|
1442
|
+
"required": true,
|
|
1443
|
+
"nullable": false
|
|
1444
|
+
}
|
|
1445
|
+
],
|
|
1446
|
+
"body": null,
|
|
1447
|
+
"response": "json"
|
|
1448
|
+
},
|
|
1449
|
+
{
|
|
1450
|
+
"operationId": "updateSegment",
|
|
1451
|
+
"method": "PATCH",
|
|
1452
|
+
"path": "/v1/segments/{id}",
|
|
1453
|
+
"summary": "Update a segment",
|
|
1454
|
+
"tag": "Segments",
|
|
1455
|
+
"params": [
|
|
1456
|
+
{
|
|
1457
|
+
"name": "id",
|
|
1458
|
+
"in": "path",
|
|
1459
|
+
"type": "string",
|
|
1460
|
+
"description": "Segment id (seg_...).",
|
|
1461
|
+
"required": true,
|
|
1462
|
+
"nullable": false
|
|
1463
|
+
}
|
|
1464
|
+
],
|
|
1465
|
+
"body": {
|
|
1466
|
+
"description": "Omitted fields are untouched.",
|
|
1467
|
+
"fields": [
|
|
1468
|
+
{
|
|
1469
|
+
"name": "name",
|
|
1470
|
+
"type": "string",
|
|
1471
|
+
"required": false,
|
|
1472
|
+
"nullable": false
|
|
1473
|
+
},
|
|
1474
|
+
{
|
|
1475
|
+
"name": "description",
|
|
1476
|
+
"type": "string",
|
|
1477
|
+
"required": false,
|
|
1478
|
+
"nullable": false
|
|
1479
|
+
},
|
|
1480
|
+
{
|
|
1481
|
+
"name": "filter",
|
|
1482
|
+
"type": "object",
|
|
1483
|
+
"description": "Replaces the whole filter.",
|
|
1484
|
+
"required": false,
|
|
1485
|
+
"nullable": false
|
|
1486
|
+
}
|
|
1487
|
+
]
|
|
1488
|
+
},
|
|
1489
|
+
"response": "json"
|
|
1490
|
+
},
|
|
1491
|
+
{
|
|
1492
|
+
"operationId": "deleteSegment",
|
|
1493
|
+
"method": "DELETE",
|
|
1494
|
+
"path": "/v1/segments/{id}",
|
|
1495
|
+
"summary": "Delete a segment",
|
|
1496
|
+
"description": "Nobody in it is affected.",
|
|
1497
|
+
"tag": "Segments",
|
|
1498
|
+
"params": [
|
|
1499
|
+
{
|
|
1500
|
+
"name": "id",
|
|
1501
|
+
"in": "path",
|
|
1502
|
+
"type": "string",
|
|
1503
|
+
"description": "Segment id (seg_...).",
|
|
1504
|
+
"required": true,
|
|
1505
|
+
"nullable": false
|
|
1506
|
+
}
|
|
1507
|
+
],
|
|
1508
|
+
"body": null,
|
|
1509
|
+
"response": "none"
|
|
1510
|
+
},
|
|
1511
|
+
{
|
|
1512
|
+
"operationId": "getCompany",
|
|
1513
|
+
"method": "GET",
|
|
1514
|
+
"path": "/v1/company",
|
|
1515
|
+
"summary": "Get the company profile",
|
|
1516
|
+
"description": "What the classifier knows about you: name, description, use cases, your own accounts, and the composed context it reads.",
|
|
1517
|
+
"tag": "Company",
|
|
1518
|
+
"params": [],
|
|
1519
|
+
"body": null,
|
|
1520
|
+
"response": "json"
|
|
1521
|
+
},
|
|
1522
|
+
{
|
|
1523
|
+
"operationId": "updateCompany",
|
|
1524
|
+
"method": "PATCH",
|
|
1525
|
+
"path": "/v1/company",
|
|
1526
|
+
"summary": "Update the company profile",
|
|
1527
|
+
"description": "Changing profile fields recomposes the classifier context; setting `context` directly overrides it until the next profile edit. Relevance scores for new mentions follow at once.",
|
|
1528
|
+
"tag": "Company",
|
|
1529
|
+
"params": [],
|
|
1530
|
+
"body": {
|
|
1531
|
+
"description": "Omitted fields are untouched.",
|
|
1532
|
+
"fields": [
|
|
1533
|
+
{
|
|
1534
|
+
"name": "name",
|
|
1535
|
+
"type": "string",
|
|
1536
|
+
"required": false,
|
|
1537
|
+
"nullable": false
|
|
1538
|
+
},
|
|
1539
|
+
{
|
|
1540
|
+
"name": "description",
|
|
1541
|
+
"type": "string",
|
|
1542
|
+
"required": false,
|
|
1543
|
+
"nullable": false
|
|
1544
|
+
},
|
|
1545
|
+
{
|
|
1546
|
+
"name": "useCases",
|
|
1547
|
+
"type": "array",
|
|
1548
|
+
"description": "Replaces the whole list.",
|
|
1549
|
+
"required": false,
|
|
1550
|
+
"nullable": false,
|
|
1551
|
+
"items": "string"
|
|
1552
|
+
},
|
|
1553
|
+
{
|
|
1554
|
+
"name": "accounts",
|
|
1555
|
+
"type": "object",
|
|
1556
|
+
"required": false,
|
|
1557
|
+
"nullable": false
|
|
1558
|
+
},
|
|
1559
|
+
{
|
|
1560
|
+
"name": "context",
|
|
1561
|
+
"type": "string",
|
|
1562
|
+
"description": "Overrides the composed context until the next profile edit.",
|
|
1563
|
+
"required": false,
|
|
1564
|
+
"nullable": false
|
|
1565
|
+
}
|
|
1566
|
+
]
|
|
1567
|
+
},
|
|
1568
|
+
"response": "json"
|
|
1569
|
+
},
|
|
1570
|
+
{
|
|
1571
|
+
"operationId": "createApiKey",
|
|
1572
|
+
"method": "POST",
|
|
1573
|
+
"path": "/v1/api-keys",
|
|
1574
|
+
"summary": "Create an API key",
|
|
1575
|
+
"description": "Mint a key for this workspace. The key itself is returned once; only its hash is stored.",
|
|
1576
|
+
"tag": "API keys",
|
|
1577
|
+
"params": [],
|
|
1578
|
+
"body": {
|
|
1579
|
+
"fields": [
|
|
1580
|
+
{
|
|
1581
|
+
"name": "name",
|
|
1582
|
+
"type": "string",
|
|
1583
|
+
"description": 'A label for the key; "default" when omitted.',
|
|
1584
|
+
"required": false,
|
|
1585
|
+
"nullable": false
|
|
1586
|
+
},
|
|
1587
|
+
{
|
|
1588
|
+
"name": "scope",
|
|
1589
|
+
"type": "string",
|
|
1590
|
+
"description": "read: GET only. write: everything.",
|
|
1591
|
+
"enum": [
|
|
1592
|
+
"read",
|
|
1593
|
+
"write"
|
|
1594
|
+
],
|
|
1595
|
+
"required": false,
|
|
1596
|
+
"nullable": false
|
|
1597
|
+
}
|
|
1598
|
+
]
|
|
1599
|
+
},
|
|
1600
|
+
"response": "json"
|
|
1601
|
+
},
|
|
1602
|
+
{
|
|
1603
|
+
"operationId": "listApiKeys",
|
|
1604
|
+
"method": "GET",
|
|
1605
|
+
"path": "/v1/api-keys",
|
|
1606
|
+
"summary": "List API keys",
|
|
1607
|
+
"tag": "API keys",
|
|
1608
|
+
"params": [],
|
|
1609
|
+
"body": null,
|
|
1610
|
+
"response": "json"
|
|
1611
|
+
},
|
|
1612
|
+
{
|
|
1613
|
+
"operationId": "revokeApiKey",
|
|
1614
|
+
"method": "DELETE",
|
|
1615
|
+
"path": "/v1/api-keys/{id}",
|
|
1616
|
+
"summary": "Revoke an API key",
|
|
1617
|
+
"description": "Takes effect at once on the API and within a few minutes on cached verifications.",
|
|
1618
|
+
"tag": "API keys",
|
|
1619
|
+
"params": [
|
|
1620
|
+
{
|
|
1621
|
+
"name": "id",
|
|
1622
|
+
"in": "path",
|
|
1623
|
+
"type": "string",
|
|
1624
|
+
"description": "API key id (key_...).",
|
|
1625
|
+
"required": true,
|
|
1626
|
+
"nullable": false
|
|
1627
|
+
}
|
|
1628
|
+
],
|
|
1629
|
+
"body": null,
|
|
1630
|
+
"response": "none"
|
|
1631
|
+
},
|
|
1632
|
+
{
|
|
1633
|
+
"operationId": "getAlert",
|
|
1634
|
+
"method": "GET",
|
|
1635
|
+
"path": "/v1/alerts/{id}",
|
|
1636
|
+
"summary": "Get an alert",
|
|
1637
|
+
"tag": "Alerts",
|
|
1638
|
+
"params": [
|
|
1639
|
+
{
|
|
1640
|
+
"name": "id",
|
|
1641
|
+
"in": "path",
|
|
1642
|
+
"type": "string",
|
|
1643
|
+
"description": "Alert id (feed_...).",
|
|
1644
|
+
"required": true,
|
|
1645
|
+
"nullable": false
|
|
1646
|
+
}
|
|
1647
|
+
],
|
|
1648
|
+
"body": null,
|
|
1649
|
+
"response": "json"
|
|
1650
|
+
},
|
|
1651
|
+
{
|
|
1652
|
+
"operationId": "updateAlert",
|
|
1653
|
+
"method": "PATCH",
|
|
1654
|
+
"path": "/v1/alerts/{id}",
|
|
1655
|
+
"summary": "Update an alert",
|
|
1656
|
+
"tag": "Alerts",
|
|
1657
|
+
"params": [
|
|
1658
|
+
{
|
|
1659
|
+
"name": "id",
|
|
1660
|
+
"in": "path",
|
|
1661
|
+
"type": "string",
|
|
1662
|
+
"description": "Alert id (feed_...).",
|
|
1663
|
+
"required": true,
|
|
1664
|
+
"nullable": false
|
|
1665
|
+
}
|
|
1666
|
+
],
|
|
1667
|
+
"body": {
|
|
1668
|
+
"description": "Omitted fields are untouched.",
|
|
1669
|
+
"fields": [
|
|
1670
|
+
{
|
|
1671
|
+
"name": "name",
|
|
1672
|
+
"type": "string",
|
|
1673
|
+
"required": false,
|
|
1674
|
+
"nullable": false
|
|
1675
|
+
},
|
|
1676
|
+
{
|
|
1677
|
+
"name": "enabled",
|
|
1678
|
+
"type": "boolean",
|
|
1679
|
+
"required": false,
|
|
1680
|
+
"nullable": false
|
|
1681
|
+
},
|
|
1682
|
+
{
|
|
1683
|
+
"name": "mode",
|
|
1684
|
+
"type": "string",
|
|
1685
|
+
"enum": [
|
|
1686
|
+
"instant",
|
|
1687
|
+
"daily"
|
|
1688
|
+
],
|
|
1689
|
+
"required": false,
|
|
1690
|
+
"nullable": false
|
|
1691
|
+
},
|
|
1692
|
+
{
|
|
1693
|
+
"name": "filter",
|
|
1694
|
+
"type": "object",
|
|
1695
|
+
"description": "Replaces the whole filter.",
|
|
1696
|
+
"required": false,
|
|
1697
|
+
"nullable": false
|
|
1698
|
+
},
|
|
1699
|
+
{
|
|
1700
|
+
"name": "schedule",
|
|
1701
|
+
"type": "object",
|
|
1702
|
+
"required": false,
|
|
1703
|
+
"nullable": true
|
|
1704
|
+
},
|
|
1705
|
+
{
|
|
1706
|
+
"name": "event",
|
|
1707
|
+
"type": "string",
|
|
1708
|
+
"required": false,
|
|
1709
|
+
"nullable": true
|
|
1710
|
+
},
|
|
1711
|
+
{
|
|
1712
|
+
"name": "channelIds",
|
|
1713
|
+
"type": "array",
|
|
1714
|
+
"description": "Replaces the whole list.",
|
|
1715
|
+
"required": false,
|
|
1716
|
+
"nullable": false,
|
|
1717
|
+
"items": "string"
|
|
1718
|
+
}
|
|
1719
|
+
]
|
|
1720
|
+
},
|
|
1721
|
+
"response": "json"
|
|
1722
|
+
},
|
|
1723
|
+
{
|
|
1724
|
+
"operationId": "deleteAlert",
|
|
1725
|
+
"method": "DELETE",
|
|
1726
|
+
"path": "/v1/alerts/{id}",
|
|
1727
|
+
"summary": "Delete an alert",
|
|
1728
|
+
"tag": "Alerts",
|
|
1729
|
+
"params": [
|
|
1730
|
+
{
|
|
1731
|
+
"name": "id",
|
|
1732
|
+
"in": "path",
|
|
1733
|
+
"type": "string",
|
|
1734
|
+
"description": "Alert id (feed_...).",
|
|
1735
|
+
"required": true,
|
|
1736
|
+
"nullable": false
|
|
1737
|
+
}
|
|
1738
|
+
],
|
|
1739
|
+
"body": null,
|
|
1740
|
+
"response": "none"
|
|
1741
|
+
},
|
|
1742
|
+
{
|
|
1743
|
+
"operationId": "listAlerts",
|
|
1744
|
+
"method": "GET",
|
|
1745
|
+
"path": "/v1/alerts",
|
|
1746
|
+
"summary": "List alerts",
|
|
1747
|
+
"tag": "Alerts",
|
|
1748
|
+
"params": [],
|
|
1749
|
+
"body": null,
|
|
1750
|
+
"response": "json"
|
|
1751
|
+
},
|
|
1752
|
+
{
|
|
1753
|
+
"operationId": "createAlert",
|
|
1754
|
+
"method": "POST",
|
|
1755
|
+
"path": "/v1/alerts",
|
|
1756
|
+
"summary": "Create an alert",
|
|
1757
|
+
"tag": "Alerts",
|
|
1758
|
+
"params": [],
|
|
1759
|
+
"body": {
|
|
1760
|
+
"fields": [
|
|
1761
|
+
{
|
|
1762
|
+
"name": "name",
|
|
1763
|
+
"type": "string",
|
|
1764
|
+
"required": true,
|
|
1765
|
+
"nullable": false
|
|
1766
|
+
},
|
|
1767
|
+
{
|
|
1768
|
+
"name": "enabled",
|
|
1769
|
+
"type": "boolean",
|
|
1770
|
+
"required": false,
|
|
1771
|
+
"nullable": false
|
|
1772
|
+
},
|
|
1773
|
+
{
|
|
1774
|
+
"name": "mode",
|
|
1775
|
+
"type": "string",
|
|
1776
|
+
"enum": [
|
|
1777
|
+
"instant",
|
|
1778
|
+
"daily"
|
|
1779
|
+
],
|
|
1780
|
+
"required": false,
|
|
1781
|
+
"nullable": false
|
|
1782
|
+
},
|
|
1783
|
+
{
|
|
1784
|
+
"name": "filter",
|
|
1785
|
+
"type": "object",
|
|
1786
|
+
"required": false,
|
|
1787
|
+
"nullable": false
|
|
1788
|
+
},
|
|
1789
|
+
{
|
|
1790
|
+
"name": "schedule",
|
|
1791
|
+
"type": "object",
|
|
1792
|
+
"description": "Required for daily alerts.",
|
|
1793
|
+
"required": false,
|
|
1794
|
+
"nullable": false
|
|
1795
|
+
},
|
|
1796
|
+
{
|
|
1797
|
+
"name": "event",
|
|
1798
|
+
"type": "string",
|
|
1799
|
+
"description": "Custom event name for webhook payloads; null for the mode default.",
|
|
1800
|
+
"required": false,
|
|
1801
|
+
"nullable": true
|
|
1802
|
+
},
|
|
1803
|
+
{
|
|
1804
|
+
"name": "channelIds",
|
|
1805
|
+
"type": "array",
|
|
1806
|
+
"description": "Channel ids from GET /v1/channels.",
|
|
1807
|
+
"required": false,
|
|
1808
|
+
"nullable": false,
|
|
1809
|
+
"items": "string"
|
|
1810
|
+
}
|
|
1811
|
+
]
|
|
1812
|
+
},
|
|
1813
|
+
"response": "json"
|
|
1814
|
+
},
|
|
1815
|
+
{
|
|
1816
|
+
"operationId": "testAlert",
|
|
1817
|
+
"method": "POST",
|
|
1818
|
+
"path": "/v1/alerts/{id}/test",
|
|
1819
|
+
"summary": "Send a test through an alert's channels",
|
|
1820
|
+
"tag": "Alerts",
|
|
1821
|
+
"params": [
|
|
1822
|
+
{
|
|
1823
|
+
"name": "id",
|
|
1824
|
+
"in": "path",
|
|
1825
|
+
"type": "string",
|
|
1826
|
+
"description": "Alert id (feed_...).",
|
|
1827
|
+
"required": true,
|
|
1828
|
+
"nullable": false
|
|
1829
|
+
}
|
|
1830
|
+
],
|
|
1831
|
+
"body": null,
|
|
1832
|
+
"response": "json"
|
|
1833
|
+
},
|
|
1834
|
+
{
|
|
1835
|
+
"operationId": "runAlertDigest",
|
|
1836
|
+
"method": "POST",
|
|
1837
|
+
"path": "/v1/alerts/{id}/run",
|
|
1838
|
+
"summary": "Send a digest now",
|
|
1839
|
+
"tag": "Alerts",
|
|
1840
|
+
"params": [
|
|
1841
|
+
{
|
|
1842
|
+
"name": "id",
|
|
1843
|
+
"in": "path",
|
|
1844
|
+
"type": "string",
|
|
1845
|
+
"description": "Alert id (feed_...).",
|
|
1846
|
+
"required": true,
|
|
1847
|
+
"nullable": false
|
|
1848
|
+
}
|
|
1849
|
+
],
|
|
1850
|
+
"body": null,
|
|
1851
|
+
"response": "json"
|
|
1852
|
+
},
|
|
1853
|
+
{
|
|
1854
|
+
"operationId": "getAnalyticsSummary",
|
|
1855
|
+
"method": "GET",
|
|
1856
|
+
"path": "/v1/analytics/summary",
|
|
1857
|
+
"summary": "Headline counts for a window",
|
|
1858
|
+
"description": "Matched and relevant mentions, distinct posts and people, sentiment, buying intent and questions, estimated reach, and where the matches stand in triage. The window is `range` (7d, 30d, 90d, 365d, ending today) or `from` and `to`, cut into days in `timezone` (UTC by default); `keywordIds` and `platforms` narrow it; `compare=true` adds the period of the same length right before it. Time axis is the publish date.",
|
|
1859
|
+
"tag": "Analytics",
|
|
1860
|
+
"params": [
|
|
1861
|
+
{
|
|
1862
|
+
"name": "range",
|
|
1863
|
+
"in": "query",
|
|
1864
|
+
"type": "string",
|
|
1865
|
+
"description": "Preset window ending today. Ignored when from or to is given. Default 30d.",
|
|
1866
|
+
"enum": [
|
|
1867
|
+
"7d",
|
|
1868
|
+
"30d",
|
|
1869
|
+
"90d",
|
|
1870
|
+
"365d"
|
|
1871
|
+
],
|
|
1872
|
+
"required": false,
|
|
1873
|
+
"nullable": false
|
|
1874
|
+
},
|
|
1875
|
+
{
|
|
1876
|
+
"name": "from",
|
|
1877
|
+
"in": "query",
|
|
1878
|
+
"type": "string",
|
|
1879
|
+
"description": "First day, YYYY-MM-DD, inclusive, in `timezone`.",
|
|
1880
|
+
"required": false,
|
|
1881
|
+
"nullable": false
|
|
1882
|
+
},
|
|
1883
|
+
{
|
|
1884
|
+
"name": "to",
|
|
1885
|
+
"in": "query",
|
|
1886
|
+
"type": "string",
|
|
1887
|
+
"description": "Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today.",
|
|
1888
|
+
"required": false,
|
|
1889
|
+
"nullable": false
|
|
1890
|
+
},
|
|
1891
|
+
{
|
|
1892
|
+
"name": "keywordIds",
|
|
1893
|
+
"in": "query",
|
|
1894
|
+
"type": "string",
|
|
1895
|
+
"description": "Comma-separated keyword ids; omit for every keyword.",
|
|
1896
|
+
"required": false,
|
|
1897
|
+
"nullable": false
|
|
1898
|
+
},
|
|
1899
|
+
{
|
|
1900
|
+
"name": "platforms",
|
|
1901
|
+
"in": "query",
|
|
1902
|
+
"type": "string",
|
|
1903
|
+
"description": "Comma-separated platforms (bluesky, hackernews, github, ...); omit for every platform.",
|
|
1904
|
+
"required": false,
|
|
1905
|
+
"nullable": false
|
|
1906
|
+
},
|
|
1907
|
+
{
|
|
1908
|
+
"name": "compare",
|
|
1909
|
+
"in": "query",
|
|
1910
|
+
"type": "string",
|
|
1911
|
+
"description": "true adds the period of the same length right before the window as `previous`.",
|
|
1912
|
+
"enum": [
|
|
1913
|
+
"true",
|
|
1914
|
+
"false"
|
|
1915
|
+
],
|
|
1916
|
+
"required": false,
|
|
1917
|
+
"nullable": false
|
|
1918
|
+
},
|
|
1919
|
+
{
|
|
1920
|
+
"name": "timezone",
|
|
1921
|
+
"in": "query",
|
|
1922
|
+
"type": "string",
|
|
1923
|
+
"description": "IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window.",
|
|
1924
|
+
"required": false,
|
|
1925
|
+
"nullable": false
|
|
1926
|
+
}
|
|
1927
|
+
],
|
|
1928
|
+
"body": null,
|
|
1929
|
+
"response": "json"
|
|
1930
|
+
},
|
|
1931
|
+
{
|
|
1932
|
+
"operationId": "getAnalyticsSeries",
|
|
1933
|
+
"method": "GET",
|
|
1934
|
+
"path": "/v1/analytics/series",
|
|
1935
|
+
"summary": "Mentions over time",
|
|
1936
|
+
"description": "Matched, relevant and sentiment counts per day or week across the window, as one total series or split per platform or per keyword with `by`. The window is `range` (7d, 30d, 90d, 365d, ending today) or `from` and `to`, cut into days in `timezone` (UTC by default); `keywordIds` and `platforms` narrow it; `compare=true` adds the period of the same length right before it. Time axis is the publish date.",
|
|
1937
|
+
"tag": "Analytics",
|
|
1938
|
+
"params": [
|
|
1939
|
+
{
|
|
1940
|
+
"name": "range",
|
|
1941
|
+
"in": "query",
|
|
1942
|
+
"type": "string",
|
|
1943
|
+
"description": "Preset window ending today. Ignored when from or to is given. Default 30d.",
|
|
1944
|
+
"enum": [
|
|
1945
|
+
"7d",
|
|
1946
|
+
"30d",
|
|
1947
|
+
"90d",
|
|
1948
|
+
"365d"
|
|
1949
|
+
],
|
|
1950
|
+
"required": false,
|
|
1951
|
+
"nullable": false
|
|
1952
|
+
},
|
|
1953
|
+
{
|
|
1954
|
+
"name": "from",
|
|
1955
|
+
"in": "query",
|
|
1956
|
+
"type": "string",
|
|
1957
|
+
"description": "First day, YYYY-MM-DD, inclusive, in `timezone`.",
|
|
1958
|
+
"required": false,
|
|
1959
|
+
"nullable": false
|
|
1960
|
+
},
|
|
1961
|
+
{
|
|
1962
|
+
"name": "to",
|
|
1963
|
+
"in": "query",
|
|
1964
|
+
"type": "string",
|
|
1965
|
+
"description": "Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today.",
|
|
1966
|
+
"required": false,
|
|
1967
|
+
"nullable": false
|
|
1968
|
+
},
|
|
1969
|
+
{
|
|
1970
|
+
"name": "keywordIds",
|
|
1971
|
+
"in": "query",
|
|
1972
|
+
"type": "string",
|
|
1973
|
+
"description": "Comma-separated keyword ids; omit for every keyword.",
|
|
1974
|
+
"required": false,
|
|
1975
|
+
"nullable": false
|
|
1976
|
+
},
|
|
1977
|
+
{
|
|
1978
|
+
"name": "platforms",
|
|
1979
|
+
"in": "query",
|
|
1980
|
+
"type": "string",
|
|
1981
|
+
"description": "Comma-separated platforms (bluesky, hackernews, github, ...); omit for every platform.",
|
|
1982
|
+
"required": false,
|
|
1983
|
+
"nullable": false
|
|
1984
|
+
},
|
|
1985
|
+
{
|
|
1986
|
+
"name": "compare",
|
|
1987
|
+
"in": "query",
|
|
1988
|
+
"type": "string",
|
|
1989
|
+
"description": "true adds the period of the same length right before the window as `previous`.",
|
|
1990
|
+
"enum": [
|
|
1991
|
+
"true",
|
|
1992
|
+
"false"
|
|
1993
|
+
],
|
|
1994
|
+
"required": false,
|
|
1995
|
+
"nullable": false
|
|
1996
|
+
},
|
|
1997
|
+
{
|
|
1998
|
+
"name": "timezone",
|
|
1999
|
+
"in": "query",
|
|
2000
|
+
"type": "string",
|
|
2001
|
+
"description": "IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window.",
|
|
2002
|
+
"required": false,
|
|
2003
|
+
"nullable": false
|
|
2004
|
+
},
|
|
2005
|
+
{
|
|
2006
|
+
"name": "bucket",
|
|
2007
|
+
"in": "query",
|
|
2008
|
+
"type": "string",
|
|
2009
|
+
"description": "Point granularity. Default: day up to 90 days, week beyond. Weeks start on Monday.",
|
|
2010
|
+
"enum": [
|
|
2011
|
+
"day",
|
|
2012
|
+
"week"
|
|
2013
|
+
],
|
|
2014
|
+
"required": false,
|
|
2015
|
+
"nullable": false
|
|
2016
|
+
},
|
|
2017
|
+
{
|
|
2018
|
+
"name": "by",
|
|
2019
|
+
"in": "query",
|
|
2020
|
+
"type": "string",
|
|
2021
|
+
"description": 'Split into one series per platform or per keyword (the top 20 by matched, the rest folded into "other"). Omit for one total series.',
|
|
2022
|
+
"enum": [
|
|
2023
|
+
"platform",
|
|
2024
|
+
"keyword"
|
|
2025
|
+
],
|
|
2026
|
+
"required": false,
|
|
2027
|
+
"nullable": false
|
|
2028
|
+
}
|
|
2029
|
+
],
|
|
2030
|
+
"body": null,
|
|
2031
|
+
"response": "json"
|
|
2032
|
+
},
|
|
2033
|
+
{
|
|
2034
|
+
"operationId": "getAnalyticsBreakdown",
|
|
2035
|
+
"method": "GET",
|
|
2036
|
+
"path": "/v1/analytics/breakdown",
|
|
2037
|
+
"summary": "Mentions grouped by one dimension",
|
|
2038
|
+
"description": "One table of matched, relevant and sentiment counts grouped by `by`: platform, keyword, sentiment, intent, status, hour (weekday and hour of day) or person. The window is `range` (7d, 30d, 90d, 365d, ending today) or `from` and `to`, cut into days in `timezone` (UTC by default); `keywordIds` and `platforms` narrow it; `compare=true` adds the period of the same length right before it. Time axis is the publish date.",
|
|
2039
|
+
"tag": "Analytics",
|
|
2040
|
+
"params": [
|
|
2041
|
+
{
|
|
2042
|
+
"name": "range",
|
|
2043
|
+
"in": "query",
|
|
2044
|
+
"type": "string",
|
|
2045
|
+
"description": "Preset window ending today. Ignored when from or to is given. Default 30d.",
|
|
2046
|
+
"enum": [
|
|
2047
|
+
"7d",
|
|
2048
|
+
"30d",
|
|
2049
|
+
"90d",
|
|
2050
|
+
"365d"
|
|
2051
|
+
],
|
|
2052
|
+
"required": false,
|
|
2053
|
+
"nullable": false
|
|
2054
|
+
},
|
|
2055
|
+
{
|
|
2056
|
+
"name": "from",
|
|
2057
|
+
"in": "query",
|
|
2058
|
+
"type": "string",
|
|
2059
|
+
"description": "First day, YYYY-MM-DD, inclusive, in `timezone`.",
|
|
2060
|
+
"required": false,
|
|
2061
|
+
"nullable": false
|
|
2062
|
+
},
|
|
2063
|
+
{
|
|
2064
|
+
"name": "to",
|
|
2065
|
+
"in": "query",
|
|
2066
|
+
"type": "string",
|
|
2067
|
+
"description": "Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today.",
|
|
2068
|
+
"required": false,
|
|
2069
|
+
"nullable": false
|
|
2070
|
+
},
|
|
2071
|
+
{
|
|
2072
|
+
"name": "keywordIds",
|
|
2073
|
+
"in": "query",
|
|
2074
|
+
"type": "string",
|
|
2075
|
+
"description": "Comma-separated keyword ids; omit for every keyword.",
|
|
2076
|
+
"required": false,
|
|
2077
|
+
"nullable": false
|
|
2078
|
+
},
|
|
2079
|
+
{
|
|
2080
|
+
"name": "platforms",
|
|
2081
|
+
"in": "query",
|
|
2082
|
+
"type": "string",
|
|
2083
|
+
"description": "Comma-separated platforms (bluesky, hackernews, github, ...); omit for every platform.",
|
|
2084
|
+
"required": false,
|
|
2085
|
+
"nullable": false
|
|
2086
|
+
},
|
|
2087
|
+
{
|
|
2088
|
+
"name": "compare",
|
|
2089
|
+
"in": "query",
|
|
2090
|
+
"type": "string",
|
|
2091
|
+
"description": "true adds the period of the same length right before the window as `previous`.",
|
|
2092
|
+
"enum": [
|
|
2093
|
+
"true",
|
|
2094
|
+
"false"
|
|
2095
|
+
],
|
|
2096
|
+
"required": false,
|
|
2097
|
+
"nullable": false
|
|
2098
|
+
},
|
|
2099
|
+
{
|
|
2100
|
+
"name": "timezone",
|
|
2101
|
+
"in": "query",
|
|
2102
|
+
"type": "string",
|
|
2103
|
+
"description": "IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window.",
|
|
2104
|
+
"required": false,
|
|
2105
|
+
"nullable": false
|
|
2106
|
+
},
|
|
2107
|
+
{
|
|
2108
|
+
"name": "by",
|
|
2109
|
+
"in": "query",
|
|
2110
|
+
"type": "string",
|
|
2111
|
+
"description": "The dimension to group by: platform, keyword, sentiment (unclassified included), intent (a mention can carry several), status (open, ignored, done), hour (weekday and hour of day in `timezone`), person (who posted; anonymous posts are left out).",
|
|
2112
|
+
"enum": [
|
|
2113
|
+
"platform",
|
|
2114
|
+
"keyword",
|
|
2115
|
+
"sentiment",
|
|
2116
|
+
"intent",
|
|
2117
|
+
"status",
|
|
2118
|
+
"hour",
|
|
2119
|
+
"person"
|
|
2120
|
+
],
|
|
2121
|
+
"required": true,
|
|
2122
|
+
"nullable": false
|
|
2123
|
+
}
|
|
2124
|
+
],
|
|
2125
|
+
"body": null,
|
|
2126
|
+
"response": "json"
|
|
2127
|
+
},
|
|
2128
|
+
{
|
|
2129
|
+
"operationId": "getShareOfVoice",
|
|
2130
|
+
"method": "GET",
|
|
2131
|
+
"path": "/v1/analytics/share-of-voice",
|
|
2132
|
+
"summary": "Brand against competitors",
|
|
2133
|
+
"description": "Every keyword matched in the window with its counts and its share of brand plus competitor matches; topic keywords are counted but stay out of the split. The window is `range` (7d, 30d, 90d, 365d, ending today) or `from` and `to`, cut into days in `timezone` (UTC by default); `keywordIds` and `platforms` narrow it; `compare=true` adds the period of the same length right before it. Time axis is the publish date.",
|
|
2134
|
+
"tag": "Analytics",
|
|
2135
|
+
"params": [
|
|
2136
|
+
{
|
|
2137
|
+
"name": "range",
|
|
2138
|
+
"in": "query",
|
|
2139
|
+
"type": "string",
|
|
2140
|
+
"description": "Preset window ending today. Ignored when from or to is given. Default 30d.",
|
|
2141
|
+
"enum": [
|
|
2142
|
+
"7d",
|
|
2143
|
+
"30d",
|
|
2144
|
+
"90d",
|
|
2145
|
+
"365d"
|
|
2146
|
+
],
|
|
2147
|
+
"required": false,
|
|
2148
|
+
"nullable": false
|
|
2149
|
+
},
|
|
2150
|
+
{
|
|
2151
|
+
"name": "from",
|
|
2152
|
+
"in": "query",
|
|
2153
|
+
"type": "string",
|
|
2154
|
+
"description": "First day, YYYY-MM-DD, inclusive, in `timezone`.",
|
|
2155
|
+
"required": false,
|
|
2156
|
+
"nullable": false
|
|
2157
|
+
},
|
|
2158
|
+
{
|
|
2159
|
+
"name": "to",
|
|
2160
|
+
"in": "query",
|
|
2161
|
+
"type": "string",
|
|
2162
|
+
"description": "Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today.",
|
|
2163
|
+
"required": false,
|
|
2164
|
+
"nullable": false
|
|
2165
|
+
},
|
|
2166
|
+
{
|
|
2167
|
+
"name": "keywordIds",
|
|
2168
|
+
"in": "query",
|
|
2169
|
+
"type": "string",
|
|
2170
|
+
"description": "Comma-separated keyword ids; omit for every keyword.",
|
|
2171
|
+
"required": false,
|
|
2172
|
+
"nullable": false
|
|
2173
|
+
},
|
|
2174
|
+
{
|
|
2175
|
+
"name": "platforms",
|
|
2176
|
+
"in": "query",
|
|
2177
|
+
"type": "string",
|
|
2178
|
+
"description": "Comma-separated platforms (bluesky, hackernews, github, ...); omit for every platform.",
|
|
2179
|
+
"required": false,
|
|
2180
|
+
"nullable": false
|
|
2181
|
+
},
|
|
2182
|
+
{
|
|
2183
|
+
"name": "compare",
|
|
2184
|
+
"in": "query",
|
|
2185
|
+
"type": "string",
|
|
2186
|
+
"description": "true adds the period of the same length right before the window as `previous`.",
|
|
2187
|
+
"enum": [
|
|
2188
|
+
"true",
|
|
2189
|
+
"false"
|
|
2190
|
+
],
|
|
2191
|
+
"required": false,
|
|
2192
|
+
"nullable": false
|
|
2193
|
+
},
|
|
2194
|
+
{
|
|
2195
|
+
"name": "timezone",
|
|
2196
|
+
"in": "query",
|
|
2197
|
+
"type": "string",
|
|
2198
|
+
"description": "IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window.",
|
|
2199
|
+
"required": false,
|
|
2200
|
+
"nullable": false
|
|
2201
|
+
}
|
|
2202
|
+
],
|
|
2203
|
+
"body": null,
|
|
2204
|
+
"response": "json"
|
|
2205
|
+
},
|
|
2206
|
+
{
|
|
2207
|
+
"operationId": "getChannel",
|
|
2208
|
+
"method": "GET",
|
|
2209
|
+
"path": "/v1/channels/{id}",
|
|
2210
|
+
"summary": "Get a channel",
|
|
2211
|
+
"tag": "Alerts",
|
|
2212
|
+
"params": [
|
|
2213
|
+
{
|
|
2214
|
+
"name": "id",
|
|
2215
|
+
"in": "path",
|
|
2216
|
+
"type": "string",
|
|
2217
|
+
"description": "Channel id (dest_...).",
|
|
2218
|
+
"required": true,
|
|
2219
|
+
"nullable": false
|
|
2220
|
+
}
|
|
2221
|
+
],
|
|
2222
|
+
"body": null,
|
|
2223
|
+
"response": "json"
|
|
2224
|
+
},
|
|
2225
|
+
{
|
|
2226
|
+
"operationId": "updateChannel",
|
|
2227
|
+
"method": "PATCH",
|
|
2228
|
+
"path": "/v1/channels/{id}",
|
|
2229
|
+
"summary": "Update a channel",
|
|
2230
|
+
"tag": "Alerts",
|
|
2231
|
+
"params": [
|
|
2232
|
+
{
|
|
2233
|
+
"name": "id",
|
|
2234
|
+
"in": "path",
|
|
2235
|
+
"type": "string",
|
|
2236
|
+
"description": "Channel id (dest_...).",
|
|
2237
|
+
"required": true,
|
|
2238
|
+
"nullable": false
|
|
2239
|
+
}
|
|
2240
|
+
],
|
|
2241
|
+
"body": {
|
|
2242
|
+
"description": "Omitted fields are untouched.",
|
|
2243
|
+
"fields": [
|
|
2244
|
+
{
|
|
2245
|
+
"name": "label",
|
|
2246
|
+
"type": "string",
|
|
2247
|
+
"required": false,
|
|
2248
|
+
"nullable": false
|
|
2249
|
+
},
|
|
2250
|
+
{
|
|
2251
|
+
"name": "url",
|
|
2252
|
+
"type": "string",
|
|
2253
|
+
"description": "Webhooks only.",
|
|
2254
|
+
"required": false,
|
|
2255
|
+
"nullable": false
|
|
2256
|
+
},
|
|
2257
|
+
{
|
|
2258
|
+
"name": "headers",
|
|
2259
|
+
"type": "object",
|
|
2260
|
+
"description": "Webhooks only; replaces the whole set.",
|
|
2261
|
+
"required": false,
|
|
2262
|
+
"nullable": false
|
|
2263
|
+
}
|
|
2264
|
+
]
|
|
2265
|
+
},
|
|
2266
|
+
"response": "json"
|
|
2267
|
+
},
|
|
2268
|
+
{
|
|
2269
|
+
"operationId": "deleteChannel",
|
|
2270
|
+
"method": "DELETE",
|
|
2271
|
+
"path": "/v1/channels/{id}",
|
|
2272
|
+
"summary": "Delete a channel",
|
|
2273
|
+
"tag": "Alerts",
|
|
2274
|
+
"params": [
|
|
2275
|
+
{
|
|
2276
|
+
"name": "id",
|
|
2277
|
+
"in": "path",
|
|
2278
|
+
"type": "string",
|
|
2279
|
+
"description": "Channel id (dest_...).",
|
|
2280
|
+
"required": true,
|
|
2281
|
+
"nullable": false
|
|
2282
|
+
}
|
|
2283
|
+
],
|
|
2284
|
+
"body": null,
|
|
2285
|
+
"response": "none"
|
|
2286
|
+
},
|
|
2287
|
+
{
|
|
2288
|
+
"operationId": "testChannel",
|
|
2289
|
+
"method": "POST",
|
|
2290
|
+
"path": "/v1/channels/{id}/test",
|
|
2291
|
+
"summary": "Send a test to a channel",
|
|
2292
|
+
"tag": "Alerts",
|
|
2293
|
+
"params": [
|
|
2294
|
+
{
|
|
2295
|
+
"name": "id",
|
|
2296
|
+
"in": "path",
|
|
2297
|
+
"type": "string",
|
|
2298
|
+
"description": "Channel id (dest_...).",
|
|
2299
|
+
"required": true,
|
|
2300
|
+
"nullable": false
|
|
2301
|
+
}
|
|
2302
|
+
],
|
|
2303
|
+
"body": null,
|
|
2304
|
+
"response": "json"
|
|
2305
|
+
},
|
|
2306
|
+
{
|
|
2307
|
+
"operationId": "rotateWebhookSecret",
|
|
2308
|
+
"method": "POST",
|
|
2309
|
+
"path": "/v1/channels/{id}/rotate-secret",
|
|
2310
|
+
"summary": "Rotate a webhook secret",
|
|
2311
|
+
"tag": "Alerts",
|
|
2312
|
+
"params": [
|
|
2313
|
+
{
|
|
2314
|
+
"name": "id",
|
|
2315
|
+
"in": "path",
|
|
2316
|
+
"type": "string",
|
|
2317
|
+
"description": "Channel id (dest_...).",
|
|
2318
|
+
"required": true,
|
|
2319
|
+
"nullable": false
|
|
2320
|
+
}
|
|
2321
|
+
],
|
|
2322
|
+
"body": null,
|
|
2323
|
+
"response": "json"
|
|
2324
|
+
},
|
|
2325
|
+
{
|
|
2326
|
+
"operationId": "listChannelDeliveries",
|
|
2327
|
+
"method": "GET",
|
|
2328
|
+
"path": "/v1/channels/{id}/deliveries",
|
|
2329
|
+
"summary": "List deliveries to a channel",
|
|
2330
|
+
"tag": "Alerts",
|
|
2331
|
+
"params": [
|
|
2332
|
+
{
|
|
2333
|
+
"name": "id",
|
|
2334
|
+
"in": "path",
|
|
2335
|
+
"type": "string",
|
|
2336
|
+
"description": "Channel id (dest_...).",
|
|
2337
|
+
"required": true,
|
|
2338
|
+
"nullable": false
|
|
2339
|
+
},
|
|
2340
|
+
{
|
|
2341
|
+
"name": "limit",
|
|
2342
|
+
"in": "query",
|
|
2343
|
+
"type": "integer",
|
|
2344
|
+
"required": false,
|
|
2345
|
+
"nullable": false
|
|
2346
|
+
}
|
|
2347
|
+
],
|
|
2348
|
+
"body": null,
|
|
2349
|
+
"response": "json"
|
|
2350
|
+
},
|
|
2351
|
+
{
|
|
2352
|
+
"operationId": "listChannels",
|
|
2353
|
+
"method": "GET",
|
|
2354
|
+
"path": "/v1/channels",
|
|
2355
|
+
"summary": "List channels",
|
|
2356
|
+
"tag": "Alerts",
|
|
2357
|
+
"params": [],
|
|
2358
|
+
"body": null,
|
|
2359
|
+
"response": "json"
|
|
2360
|
+
},
|
|
2361
|
+
{
|
|
2362
|
+
"operationId": "createChannel",
|
|
2363
|
+
"method": "POST",
|
|
2364
|
+
"path": "/v1/channels",
|
|
2365
|
+
"summary": "Create a channel",
|
|
2366
|
+
"tag": "Alerts",
|
|
2367
|
+
"params": [],
|
|
2368
|
+
"body": {
|
|
2369
|
+
"fields": [
|
|
2370
|
+
{
|
|
2371
|
+
"name": "kind",
|
|
2372
|
+
"type": "string",
|
|
2373
|
+
"enum": [
|
|
2374
|
+
"slack",
|
|
2375
|
+
"email",
|
|
2376
|
+
"webhook"
|
|
2377
|
+
],
|
|
2378
|
+
"required": false,
|
|
2379
|
+
"nullable": false
|
|
2380
|
+
},
|
|
2381
|
+
{
|
|
2382
|
+
"name": "channelId",
|
|
2383
|
+
"type": "string",
|
|
2384
|
+
"description": "A Slack channel id from the connected workspace.",
|
|
2385
|
+
"required": false,
|
|
2386
|
+
"nullable": false
|
|
2387
|
+
},
|
|
2388
|
+
{
|
|
2389
|
+
"name": "channelName",
|
|
2390
|
+
"type": "string",
|
|
2391
|
+
"required": false,
|
|
2392
|
+
"nullable": false
|
|
2393
|
+
},
|
|
2394
|
+
{
|
|
2395
|
+
"name": "emails",
|
|
2396
|
+
"type": "array",
|
|
2397
|
+
"description": "Each address gets a confirmation link; workspace members are confirmed on sight.",
|
|
2398
|
+
"required": false,
|
|
2399
|
+
"nullable": false,
|
|
2400
|
+
"items": "string"
|
|
2401
|
+
},
|
|
2402
|
+
{
|
|
2403
|
+
"name": "url",
|
|
2404
|
+
"type": "string",
|
|
2405
|
+
"required": false,
|
|
2406
|
+
"nullable": false
|
|
2407
|
+
},
|
|
2408
|
+
{
|
|
2409
|
+
"name": "label",
|
|
2410
|
+
"type": "string",
|
|
2411
|
+
"required": false,
|
|
2412
|
+
"nullable": false
|
|
2413
|
+
},
|
|
2414
|
+
{
|
|
2415
|
+
"name": "headers",
|
|
2416
|
+
"type": "object",
|
|
2417
|
+
"required": false,
|
|
2418
|
+
"nullable": false
|
|
2419
|
+
}
|
|
2420
|
+
]
|
|
2421
|
+
},
|
|
2422
|
+
"response": "json"
|
|
2423
|
+
}
|
|
2424
|
+
];
|
|
2425
|
+
|
|
2426
|
+
// src/output.ts
|
|
2427
|
+
var isScalar = (v) => v === null || ["string", "number", "boolean"].includes(typeof v);
|
|
2428
|
+
var cell = (v) => {
|
|
2429
|
+
if (v === null) return "";
|
|
2430
|
+
if (typeof v === "string") return v.length > 48 ? `${v.slice(0, 47)}\u2026` : v.replace(/\s+/g, " ");
|
|
2431
|
+
return String(v);
|
|
2432
|
+
};
|
|
2433
|
+
function renderTable(rows) {
|
|
2434
|
+
const first = rows[0];
|
|
2435
|
+
if (!first) return "(no rows)";
|
|
2436
|
+
const columns = Object.keys(first).filter((k) => isScalar(first[k])).slice(0, 8);
|
|
2437
|
+
if (columns.length === 0) return JSON.stringify(rows, null, 2);
|
|
2438
|
+
const lines = rows.map((row) => columns.map((c) => cell(isScalar(row[c]) ? row[c] : JSON.stringify(row[c]))));
|
|
2439
|
+
const widths = columns.map((c, i) => Math.max(c.length, ...lines.map((l) => l[i]?.length ?? 0)));
|
|
2440
|
+
const pad = (s, w) => s.padEnd(w);
|
|
2441
|
+
const header = columns.map((c, i) => pad(c, widths[i] ?? c.length)).join(" ");
|
|
2442
|
+
const rule = widths.map((w) => "-".repeat(w)).join(" ");
|
|
2443
|
+
const body = lines.map((l) => l.map((s, i) => pad(s, widths[i] ?? s.length)).join(" "));
|
|
2444
|
+
return [header, rule, ...body].join("\n");
|
|
2445
|
+
}
|
|
2446
|
+
function formatOutput(value, options) {
|
|
2447
|
+
if (options.table) {
|
|
2448
|
+
const rows = Array.isArray(value) ? value : value !== null && typeof value === "object" && Array.isArray(value.data) ? value.data : null;
|
|
2449
|
+
if (rows && rows.every((r) => r !== null && typeof r === "object")) {
|
|
2450
|
+
return renderTable(rows);
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
return options.pretty ? JSON.stringify(value, null, 2) : JSON.stringify(value);
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2456
|
+
// ../sdk/src/generated/core/bodySerializer.gen.ts
|
|
2457
|
+
var jsonBodySerializer = {
|
|
2458
|
+
bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value)
|
|
2459
|
+
};
|
|
2460
|
+
|
|
2461
|
+
// ../sdk/src/generated/core/params.gen.ts
|
|
2462
|
+
var extraPrefixesMap = {
|
|
2463
|
+
$body_: "body",
|
|
2464
|
+
$headers_: "headers",
|
|
2465
|
+
$path_: "path",
|
|
2466
|
+
$query_: "query"
|
|
2467
|
+
};
|
|
2468
|
+
var extraPrefixes = Object.entries(extraPrefixesMap);
|
|
2469
|
+
|
|
2470
|
+
// ../sdk/src/generated/core/serverSentEvents.gen.ts
|
|
2471
|
+
function createSseClient({
|
|
2472
|
+
onRequest,
|
|
2473
|
+
onSseError,
|
|
2474
|
+
onSseEvent,
|
|
2475
|
+
responseTransformer,
|
|
2476
|
+
responseValidator,
|
|
2477
|
+
sseDefaultRetryDelay,
|
|
2478
|
+
sseMaxRetryAttempts,
|
|
2479
|
+
sseMaxRetryDelay,
|
|
2480
|
+
sseSleepFn,
|
|
2481
|
+
url,
|
|
2482
|
+
...options
|
|
2483
|
+
}) {
|
|
2484
|
+
let lastEventId;
|
|
2485
|
+
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
2486
|
+
const createStream = async function* () {
|
|
2487
|
+
let retryDelay = sseDefaultRetryDelay ?? 3e3;
|
|
2488
|
+
let attempt = 0;
|
|
2489
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
2490
|
+
while (true) {
|
|
2491
|
+
if (signal.aborted) break;
|
|
2492
|
+
attempt++;
|
|
2493
|
+
const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
|
|
2494
|
+
if (lastEventId !== void 0) {
|
|
2495
|
+
headers.set("Last-Event-ID", lastEventId);
|
|
2496
|
+
}
|
|
2497
|
+
try {
|
|
2498
|
+
const requestInit = {
|
|
2499
|
+
redirect: "follow",
|
|
2500
|
+
...options,
|
|
2501
|
+
body: options.serializedBody,
|
|
2502
|
+
headers,
|
|
2503
|
+
signal
|
|
2504
|
+
};
|
|
2505
|
+
let request = new Request(url, requestInit);
|
|
2506
|
+
if (onRequest) {
|
|
2507
|
+
request = await onRequest(url, requestInit);
|
|
2508
|
+
}
|
|
2509
|
+
const _fetch = options.fetch ?? globalThis.fetch;
|
|
2510
|
+
const response = await _fetch(request);
|
|
2511
|
+
if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
|
|
2512
|
+
if (!response.body) throw new Error("No body in SSE response");
|
|
2513
|
+
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
2514
|
+
let buffer = "";
|
|
2515
|
+
const abortHandler = () => {
|
|
2516
|
+
try {
|
|
2517
|
+
reader.cancel();
|
|
2518
|
+
} catch {
|
|
2519
|
+
}
|
|
2520
|
+
};
|
|
2521
|
+
signal.addEventListener("abort", abortHandler);
|
|
2522
|
+
try {
|
|
2523
|
+
while (true) {
|
|
2524
|
+
const { done, value } = await reader.read();
|
|
2525
|
+
if (done) break;
|
|
2526
|
+
buffer += value;
|
|
2527
|
+
buffer = buffer.replace(/\r\n?/g, "\n");
|
|
2528
|
+
const chunks = buffer.split("\n\n");
|
|
2529
|
+
buffer = chunks.pop() ?? "";
|
|
2530
|
+
for (const chunk of chunks) {
|
|
2531
|
+
const lines = chunk.split("\n");
|
|
2532
|
+
const dataLines = [];
|
|
2533
|
+
let eventName;
|
|
2534
|
+
for (const line of lines) {
|
|
2535
|
+
if (line.startsWith("data:")) {
|
|
2536
|
+
dataLines.push(line.replace(/^data:\s*/, ""));
|
|
2537
|
+
} else if (line.startsWith("event:")) {
|
|
2538
|
+
eventName = line.replace(/^event:\s*/, "");
|
|
2539
|
+
} else if (line.startsWith("id:")) {
|
|
2540
|
+
lastEventId = line.replace(/^id:\s*/, "");
|
|
2541
|
+
} else if (line.startsWith("retry:")) {
|
|
2542
|
+
const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
|
|
2543
|
+
if (!Number.isNaN(parsed)) {
|
|
2544
|
+
retryDelay = parsed;
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
let data;
|
|
2549
|
+
let parsedJson = false;
|
|
2550
|
+
if (dataLines.length) {
|
|
2551
|
+
const rawData = dataLines.join("\n");
|
|
2552
|
+
try {
|
|
2553
|
+
data = JSON.parse(rawData);
|
|
2554
|
+
parsedJson = true;
|
|
2555
|
+
} catch {
|
|
2556
|
+
data = rawData;
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
if (parsedJson) {
|
|
2560
|
+
if (responseValidator) {
|
|
2561
|
+
await responseValidator(data);
|
|
2562
|
+
}
|
|
2563
|
+
if (responseTransformer) {
|
|
2564
|
+
data = await responseTransformer(data);
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
onSseEvent?.({
|
|
2568
|
+
data,
|
|
2569
|
+
event: eventName,
|
|
2570
|
+
id: lastEventId,
|
|
2571
|
+
retry: retryDelay
|
|
2572
|
+
});
|
|
2573
|
+
if (dataLines.length) {
|
|
2574
|
+
yield data;
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
} finally {
|
|
2579
|
+
signal.removeEventListener("abort", abortHandler);
|
|
2580
|
+
reader.releaseLock();
|
|
2581
|
+
}
|
|
2582
|
+
break;
|
|
2583
|
+
} catch (error) {
|
|
2584
|
+
onSseError?.(error);
|
|
2585
|
+
if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
|
|
2586
|
+
break;
|
|
2587
|
+
}
|
|
2588
|
+
const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4);
|
|
2589
|
+
await sleep(backoff);
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
};
|
|
2593
|
+
const stream = createStream();
|
|
2594
|
+
return { stream };
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
// ../sdk/src/generated/core/pathSerializer.gen.ts
|
|
2598
|
+
var separatorArrayExplode = (style) => {
|
|
2599
|
+
switch (style) {
|
|
2600
|
+
case "label":
|
|
2601
|
+
return ".";
|
|
2602
|
+
case "matrix":
|
|
2603
|
+
return ";";
|
|
2604
|
+
case "simple":
|
|
2605
|
+
return ",";
|
|
2606
|
+
default:
|
|
2607
|
+
return "&";
|
|
2608
|
+
}
|
|
2609
|
+
};
|
|
2610
|
+
var separatorArrayNoExplode = (style) => {
|
|
2611
|
+
switch (style) {
|
|
2612
|
+
case "form":
|
|
2613
|
+
return ",";
|
|
2614
|
+
case "pipeDelimited":
|
|
2615
|
+
return "|";
|
|
2616
|
+
case "spaceDelimited":
|
|
2617
|
+
return "%20";
|
|
2618
|
+
default:
|
|
2619
|
+
return ",";
|
|
2620
|
+
}
|
|
2621
|
+
};
|
|
2622
|
+
var separatorObjectExplode = (style) => {
|
|
2623
|
+
switch (style) {
|
|
2624
|
+
case "label":
|
|
2625
|
+
return ".";
|
|
2626
|
+
case "matrix":
|
|
2627
|
+
return ";";
|
|
2628
|
+
case "simple":
|
|
2629
|
+
return ",";
|
|
2630
|
+
default:
|
|
2631
|
+
return "&";
|
|
2632
|
+
}
|
|
2633
|
+
};
|
|
2634
|
+
var serializeArrayParam = ({
|
|
2635
|
+
allowReserved,
|
|
2636
|
+
explode,
|
|
2637
|
+
name,
|
|
2638
|
+
style,
|
|
2639
|
+
value
|
|
2640
|
+
}) => {
|
|
2641
|
+
if (!explode) {
|
|
2642
|
+
const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
|
|
2643
|
+
switch (style) {
|
|
2644
|
+
case "label":
|
|
2645
|
+
return `.${joinedValues2}`;
|
|
2646
|
+
case "matrix":
|
|
2647
|
+
return `;${name}=${joinedValues2}`;
|
|
2648
|
+
case "simple":
|
|
2649
|
+
return joinedValues2;
|
|
2650
|
+
default:
|
|
2651
|
+
return `${name}=${joinedValues2}`;
|
|
2652
|
+
}
|
|
2653
|
+
}
|
|
2654
|
+
const separator = separatorArrayExplode(style);
|
|
2655
|
+
const joinedValues = value.map((v) => {
|
|
2656
|
+
if (style === "label" || style === "simple") {
|
|
2657
|
+
return allowReserved ? v : encodeURIComponent(v);
|
|
2658
|
+
}
|
|
2659
|
+
return serializePrimitiveParam({
|
|
2660
|
+
allowReserved,
|
|
2661
|
+
name,
|
|
2662
|
+
value: v
|
|
2663
|
+
});
|
|
2664
|
+
}).join(separator);
|
|
2665
|
+
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
2666
|
+
};
|
|
2667
|
+
var serializePrimitiveParam = ({
|
|
2668
|
+
allowReserved,
|
|
2669
|
+
name,
|
|
2670
|
+
value
|
|
2671
|
+
}) => {
|
|
2672
|
+
if (value === void 0 || value === null) {
|
|
2673
|
+
return "";
|
|
2674
|
+
}
|
|
2675
|
+
if (typeof value === "object") {
|
|
2676
|
+
throw new Error(
|
|
2677
|
+
"Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
|
|
2678
|
+
);
|
|
2679
|
+
}
|
|
2680
|
+
return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
|
|
2681
|
+
};
|
|
2682
|
+
var serializeObjectParam = ({
|
|
2683
|
+
allowReserved,
|
|
2684
|
+
explode,
|
|
2685
|
+
name,
|
|
2686
|
+
style,
|
|
2687
|
+
value,
|
|
2688
|
+
valueOnly
|
|
2689
|
+
}) => {
|
|
2690
|
+
if (value instanceof Date) {
|
|
2691
|
+
return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
|
|
2692
|
+
}
|
|
2693
|
+
if (style !== "deepObject" && !explode) {
|
|
2694
|
+
let values = [];
|
|
2695
|
+
Object.entries(value).forEach(([key, v]) => {
|
|
2696
|
+
values = [...values, key, allowReserved ? v : encodeURIComponent(v)];
|
|
2697
|
+
});
|
|
2698
|
+
const joinedValues2 = values.join(",");
|
|
2699
|
+
switch (style) {
|
|
2700
|
+
case "form":
|
|
2701
|
+
return `${name}=${joinedValues2}`;
|
|
2702
|
+
case "label":
|
|
2703
|
+
return `.${joinedValues2}`;
|
|
2704
|
+
case "matrix":
|
|
2705
|
+
return `;${name}=${joinedValues2}`;
|
|
2706
|
+
default:
|
|
2707
|
+
return joinedValues2;
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
const separator = separatorObjectExplode(style);
|
|
2711
|
+
const joinedValues = Object.entries(value).map(
|
|
2712
|
+
([key, v]) => serializePrimitiveParam({
|
|
2713
|
+
allowReserved,
|
|
2714
|
+
name: style === "deepObject" ? `${name}[${key}]` : key,
|
|
2715
|
+
value: v
|
|
2716
|
+
})
|
|
2717
|
+
).join(separator);
|
|
2718
|
+
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
2719
|
+
};
|
|
2720
|
+
|
|
2721
|
+
// ../sdk/src/generated/core/utils.gen.ts
|
|
2722
|
+
var PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
2723
|
+
var defaultPathSerializer = ({ path, url: _url }) => {
|
|
2724
|
+
let url = _url;
|
|
2725
|
+
const matches = _url.match(PATH_PARAM_RE);
|
|
2726
|
+
if (matches) {
|
|
2727
|
+
for (const match of matches) {
|
|
2728
|
+
let explode = false;
|
|
2729
|
+
let name = match.substring(1, match.length - 1);
|
|
2730
|
+
let style = "simple";
|
|
2731
|
+
if (name.endsWith("*")) {
|
|
2732
|
+
explode = true;
|
|
2733
|
+
name = name.substring(0, name.length - 1);
|
|
2734
|
+
}
|
|
2735
|
+
if (name.startsWith(".")) {
|
|
2736
|
+
name = name.substring(1);
|
|
2737
|
+
style = "label";
|
|
2738
|
+
} else if (name.startsWith(";")) {
|
|
2739
|
+
name = name.substring(1);
|
|
2740
|
+
style = "matrix";
|
|
2741
|
+
}
|
|
2742
|
+
const value = path[name];
|
|
2743
|
+
if (value === void 0 || value === null) {
|
|
2744
|
+
continue;
|
|
2745
|
+
}
|
|
2746
|
+
if (Array.isArray(value)) {
|
|
2747
|
+
url = url.replace(match, serializeArrayParam({ explode, name, style, value }));
|
|
2748
|
+
continue;
|
|
2749
|
+
}
|
|
2750
|
+
if (typeof value === "object") {
|
|
2751
|
+
url = url.replace(
|
|
2752
|
+
match,
|
|
2753
|
+
serializeObjectParam({
|
|
2754
|
+
explode,
|
|
2755
|
+
name,
|
|
2756
|
+
style,
|
|
2757
|
+
value,
|
|
2758
|
+
valueOnly: true
|
|
2759
|
+
})
|
|
2760
|
+
);
|
|
2761
|
+
continue;
|
|
2762
|
+
}
|
|
2763
|
+
if (style === "matrix") {
|
|
2764
|
+
url = url.replace(
|
|
2765
|
+
match,
|
|
2766
|
+
`;${serializePrimitiveParam({
|
|
2767
|
+
name,
|
|
2768
|
+
value
|
|
2769
|
+
})}`
|
|
2770
|
+
);
|
|
2771
|
+
continue;
|
|
2772
|
+
}
|
|
2773
|
+
const replaceValue = encodeURIComponent(
|
|
2774
|
+
style === "label" ? `.${value}` : value
|
|
2775
|
+
);
|
|
2776
|
+
url = url.replace(match, replaceValue);
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2779
|
+
return url;
|
|
2780
|
+
};
|
|
2781
|
+
var getUrl = ({
|
|
2782
|
+
baseUrl,
|
|
2783
|
+
path,
|
|
2784
|
+
query,
|
|
2785
|
+
querySerializer,
|
|
2786
|
+
url: _url
|
|
2787
|
+
}) => {
|
|
2788
|
+
const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
|
|
2789
|
+
let url = (baseUrl ?? "") + pathUrl;
|
|
2790
|
+
if (path) {
|
|
2791
|
+
url = defaultPathSerializer({ path, url });
|
|
2792
|
+
}
|
|
2793
|
+
let search = query ? querySerializer(query) : "";
|
|
2794
|
+
if (search.startsWith("?")) {
|
|
2795
|
+
search = search.substring(1);
|
|
2796
|
+
}
|
|
2797
|
+
if (search) {
|
|
2798
|
+
url += `?${search}`;
|
|
2799
|
+
}
|
|
2800
|
+
return url;
|
|
2801
|
+
};
|
|
2802
|
+
function getValidRequestBody(options) {
|
|
2803
|
+
const hasBody = options.body !== void 0;
|
|
2804
|
+
const isSerializedBody = hasBody && options.bodySerializer;
|
|
2805
|
+
if (isSerializedBody) {
|
|
2806
|
+
if ("serializedBody" in options) {
|
|
2807
|
+
const hasSerializedBody = options.serializedBody !== void 0 && options.serializedBody !== "";
|
|
2808
|
+
return hasSerializedBody ? options.serializedBody : null;
|
|
2809
|
+
}
|
|
2810
|
+
return options.body !== "" ? options.body : null;
|
|
2811
|
+
}
|
|
2812
|
+
if (hasBody) {
|
|
2813
|
+
return options.body;
|
|
2814
|
+
}
|
|
2815
|
+
return void 0;
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2818
|
+
// ../sdk/src/generated/core/auth.gen.ts
|
|
2819
|
+
var getAuthToken = async (auth, callback) => {
|
|
2820
|
+
const token = typeof callback === "function" ? await callback(auth) : callback;
|
|
2821
|
+
if (!token) {
|
|
2822
|
+
return;
|
|
2823
|
+
}
|
|
2824
|
+
if (auth.scheme === "bearer") {
|
|
2825
|
+
return `Bearer ${token}`;
|
|
2826
|
+
}
|
|
2827
|
+
if (auth.scheme === "basic") {
|
|
2828
|
+
return `Basic ${btoa(token)}`;
|
|
2829
|
+
}
|
|
2830
|
+
return token;
|
|
2831
|
+
};
|
|
2832
|
+
|
|
2833
|
+
// ../sdk/src/generated/client/utils.gen.ts
|
|
2834
|
+
var createQuerySerializer = ({
|
|
2835
|
+
parameters = {},
|
|
2836
|
+
...args
|
|
2837
|
+
} = {}) => {
|
|
2838
|
+
const querySerializer = (queryParams) => {
|
|
2839
|
+
const search = [];
|
|
2840
|
+
if (queryParams && typeof queryParams === "object") {
|
|
2841
|
+
for (const name in queryParams) {
|
|
2842
|
+
const value = queryParams[name];
|
|
2843
|
+
if (value === void 0 || value === null) {
|
|
2844
|
+
continue;
|
|
2845
|
+
}
|
|
2846
|
+
const options = parameters[name] || args;
|
|
2847
|
+
if (Array.isArray(value)) {
|
|
2848
|
+
const serializedArray = serializeArrayParam({
|
|
2849
|
+
allowReserved: options.allowReserved,
|
|
2850
|
+
explode: true,
|
|
2851
|
+
name,
|
|
2852
|
+
style: "form",
|
|
2853
|
+
value,
|
|
2854
|
+
...options.array
|
|
2855
|
+
});
|
|
2856
|
+
if (serializedArray) search.push(serializedArray);
|
|
2857
|
+
} else if (typeof value === "object") {
|
|
2858
|
+
const serializedObject = serializeObjectParam({
|
|
2859
|
+
allowReserved: options.allowReserved,
|
|
2860
|
+
explode: true,
|
|
2861
|
+
name,
|
|
2862
|
+
style: "deepObject",
|
|
2863
|
+
value,
|
|
2864
|
+
...options.object
|
|
2865
|
+
});
|
|
2866
|
+
if (serializedObject) search.push(serializedObject);
|
|
2867
|
+
} else {
|
|
2868
|
+
const serializedPrimitive = serializePrimitiveParam({
|
|
2869
|
+
allowReserved: options.allowReserved,
|
|
2870
|
+
name,
|
|
2871
|
+
value
|
|
2872
|
+
});
|
|
2873
|
+
if (serializedPrimitive) search.push(serializedPrimitive);
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
return search.join("&");
|
|
2878
|
+
};
|
|
2879
|
+
return querySerializer;
|
|
2880
|
+
};
|
|
2881
|
+
var getParseAs = (contentType) => {
|
|
2882
|
+
if (!contentType) {
|
|
2883
|
+
return "stream";
|
|
2884
|
+
}
|
|
2885
|
+
const cleanContent = contentType.split(";")[0]?.trim();
|
|
2886
|
+
if (!cleanContent) {
|
|
2887
|
+
return;
|
|
2888
|
+
}
|
|
2889
|
+
if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
|
|
2890
|
+
return "json";
|
|
2891
|
+
}
|
|
2892
|
+
if (cleanContent === "multipart/form-data") {
|
|
2893
|
+
return "formData";
|
|
2894
|
+
}
|
|
2895
|
+
if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
|
|
2896
|
+
return "blob";
|
|
2897
|
+
}
|
|
2898
|
+
if (cleanContent.startsWith("text/")) {
|
|
2899
|
+
return "text";
|
|
2900
|
+
}
|
|
2901
|
+
return;
|
|
2902
|
+
};
|
|
2903
|
+
var checkForExistence = (options, name) => {
|
|
2904
|
+
if (!name) {
|
|
2905
|
+
return false;
|
|
2906
|
+
}
|
|
2907
|
+
if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
|
|
2908
|
+
return true;
|
|
2909
|
+
}
|
|
2910
|
+
return false;
|
|
2911
|
+
};
|
|
2912
|
+
async function setAuthParams(options) {
|
|
2913
|
+
for (const auth of options.security ?? []) {
|
|
2914
|
+
if (checkForExistence(options, auth.name)) {
|
|
2915
|
+
continue;
|
|
2916
|
+
}
|
|
2917
|
+
const token = await getAuthToken(auth, options.auth);
|
|
2918
|
+
if (!token) {
|
|
2919
|
+
continue;
|
|
2920
|
+
}
|
|
2921
|
+
const name = auth.name ?? "Authorization";
|
|
2922
|
+
switch (auth.in) {
|
|
2923
|
+
case "query":
|
|
2924
|
+
if (!options.query) {
|
|
2925
|
+
options.query = {};
|
|
2926
|
+
}
|
|
2927
|
+
options.query[name] = token;
|
|
2928
|
+
break;
|
|
2929
|
+
case "cookie":
|
|
2930
|
+
options.headers.append("Cookie", `${name}=${token}`);
|
|
2931
|
+
break;
|
|
2932
|
+
case "header":
|
|
2933
|
+
default:
|
|
2934
|
+
options.headers.set(name, token);
|
|
2935
|
+
break;
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
var buildUrl = (options) => getUrl({
|
|
2940
|
+
baseUrl: options.baseUrl,
|
|
2941
|
+
path: options.path,
|
|
2942
|
+
query: options.query,
|
|
2943
|
+
querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
|
|
2944
|
+
url: options.url
|
|
2945
|
+
});
|
|
2946
|
+
var mergeConfigs = (a, b) => {
|
|
2947
|
+
const config = { ...a, ...b };
|
|
2948
|
+
if (config.baseUrl?.endsWith("/")) {
|
|
2949
|
+
config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
|
|
2950
|
+
}
|
|
2951
|
+
config.headers = mergeHeaders(a.headers, b.headers);
|
|
2952
|
+
return config;
|
|
2953
|
+
};
|
|
2954
|
+
var headersEntries = (headers) => {
|
|
2955
|
+
const entries = [];
|
|
2956
|
+
headers.forEach((value, key) => {
|
|
2957
|
+
entries.push([key, value]);
|
|
2958
|
+
});
|
|
2959
|
+
return entries;
|
|
2960
|
+
};
|
|
2961
|
+
var mergeHeaders = (...headers) => {
|
|
2962
|
+
const mergedHeaders = new Headers();
|
|
2963
|
+
for (const header of headers) {
|
|
2964
|
+
if (!header) {
|
|
2965
|
+
continue;
|
|
2966
|
+
}
|
|
2967
|
+
const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
|
|
2968
|
+
for (const [key, value] of iterator) {
|
|
2969
|
+
if (value === null) {
|
|
2970
|
+
mergedHeaders.delete(key);
|
|
2971
|
+
} else if (Array.isArray(value)) {
|
|
2972
|
+
for (const v of value) {
|
|
2973
|
+
mergedHeaders.append(key, v);
|
|
2974
|
+
}
|
|
2975
|
+
} else if (value !== void 0) {
|
|
2976
|
+
mergedHeaders.set(
|
|
2977
|
+
key,
|
|
2978
|
+
typeof value === "object" ? JSON.stringify(value) : value
|
|
2979
|
+
);
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
return mergedHeaders;
|
|
2984
|
+
};
|
|
2985
|
+
var Interceptors = class {
|
|
2986
|
+
fns = [];
|
|
2987
|
+
clear() {
|
|
2988
|
+
this.fns = [];
|
|
2989
|
+
}
|
|
2990
|
+
eject(id) {
|
|
2991
|
+
const index = this.getInterceptorIndex(id);
|
|
2992
|
+
if (this.fns[index]) {
|
|
2993
|
+
this.fns[index] = null;
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
exists(id) {
|
|
2997
|
+
const index = this.getInterceptorIndex(id);
|
|
2998
|
+
return Boolean(this.fns[index]);
|
|
2999
|
+
}
|
|
3000
|
+
getInterceptorIndex(id) {
|
|
3001
|
+
if (typeof id === "number") {
|
|
3002
|
+
return this.fns[id] ? id : -1;
|
|
3003
|
+
}
|
|
3004
|
+
return this.fns.indexOf(id);
|
|
3005
|
+
}
|
|
3006
|
+
update(id, fn) {
|
|
3007
|
+
const index = this.getInterceptorIndex(id);
|
|
3008
|
+
if (this.fns[index]) {
|
|
3009
|
+
this.fns[index] = fn;
|
|
3010
|
+
return id;
|
|
3011
|
+
}
|
|
3012
|
+
return false;
|
|
3013
|
+
}
|
|
3014
|
+
use(fn) {
|
|
3015
|
+
this.fns.push(fn);
|
|
3016
|
+
return this.fns.length - 1;
|
|
3017
|
+
}
|
|
3018
|
+
};
|
|
3019
|
+
var createInterceptors = () => ({
|
|
3020
|
+
error: new Interceptors(),
|
|
3021
|
+
request: new Interceptors(),
|
|
3022
|
+
response: new Interceptors()
|
|
3023
|
+
});
|
|
3024
|
+
var defaultQuerySerializer = createQuerySerializer({
|
|
3025
|
+
allowReserved: false,
|
|
3026
|
+
array: {
|
|
3027
|
+
explode: true,
|
|
3028
|
+
style: "form"
|
|
3029
|
+
},
|
|
3030
|
+
object: {
|
|
3031
|
+
explode: true,
|
|
3032
|
+
style: "deepObject"
|
|
3033
|
+
}
|
|
3034
|
+
});
|
|
3035
|
+
var defaultHeaders = {
|
|
3036
|
+
"Content-Type": "application/json"
|
|
3037
|
+
};
|
|
3038
|
+
var createConfig = (override = {}) => ({
|
|
3039
|
+
...jsonBodySerializer,
|
|
3040
|
+
headers: defaultHeaders,
|
|
3041
|
+
parseAs: "auto",
|
|
3042
|
+
querySerializer: defaultQuerySerializer,
|
|
3043
|
+
...override
|
|
3044
|
+
});
|
|
3045
|
+
|
|
3046
|
+
// ../sdk/src/generated/client/client.gen.ts
|
|
3047
|
+
var createClient = (config = {}) => {
|
|
3048
|
+
let _config = mergeConfigs(createConfig(), config);
|
|
3049
|
+
const getConfig = () => ({ ..._config });
|
|
3050
|
+
const setConfig = (config2) => {
|
|
3051
|
+
_config = mergeConfigs(_config, config2);
|
|
3052
|
+
return getConfig();
|
|
3053
|
+
};
|
|
3054
|
+
const interceptors = createInterceptors();
|
|
3055
|
+
const beforeRequest = async (options) => {
|
|
3056
|
+
const opts = {
|
|
3057
|
+
..._config,
|
|
3058
|
+
...options,
|
|
3059
|
+
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
|
|
3060
|
+
headers: mergeHeaders(_config.headers, options.headers),
|
|
3061
|
+
serializedBody: void 0
|
|
3062
|
+
};
|
|
3063
|
+
if (opts.security) {
|
|
3064
|
+
await setAuthParams(opts);
|
|
3065
|
+
}
|
|
3066
|
+
if (opts.requestValidator) {
|
|
3067
|
+
await opts.requestValidator(opts);
|
|
3068
|
+
}
|
|
3069
|
+
if (opts.body !== void 0 && opts.bodySerializer) {
|
|
3070
|
+
opts.serializedBody = opts.bodySerializer(opts.body);
|
|
3071
|
+
}
|
|
3072
|
+
if (opts.body === void 0 || opts.serializedBody === "") {
|
|
3073
|
+
opts.headers.delete("Content-Type");
|
|
3074
|
+
}
|
|
3075
|
+
const resolvedOpts = opts;
|
|
3076
|
+
const url = buildUrl(resolvedOpts);
|
|
3077
|
+
return { opts: resolvedOpts, url };
|
|
3078
|
+
};
|
|
3079
|
+
const request = async (options) => {
|
|
3080
|
+
const throwOnError = options.throwOnError ?? _config.throwOnError;
|
|
3081
|
+
const responseStyle = options.responseStyle ?? _config.responseStyle;
|
|
3082
|
+
let request2;
|
|
3083
|
+
let response;
|
|
3084
|
+
try {
|
|
3085
|
+
const { opts, url } = await beforeRequest(options);
|
|
3086
|
+
const requestInit = {
|
|
3087
|
+
redirect: "follow",
|
|
3088
|
+
...opts,
|
|
3089
|
+
body: getValidRequestBody(opts)
|
|
3090
|
+
};
|
|
3091
|
+
request2 = new Request(url, requestInit);
|
|
3092
|
+
for (const fn of interceptors.request.fns) {
|
|
3093
|
+
if (fn) {
|
|
3094
|
+
request2 = await fn(request2, opts);
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
const _fetch = opts.fetch;
|
|
3098
|
+
response = await _fetch(request2);
|
|
3099
|
+
for (const fn of interceptors.response.fns) {
|
|
3100
|
+
if (fn) {
|
|
3101
|
+
response = await fn(response, request2, opts);
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
const result = {
|
|
3105
|
+
request: request2,
|
|
3106
|
+
response
|
|
3107
|
+
};
|
|
3108
|
+
if (response.ok) {
|
|
3109
|
+
const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
|
|
3110
|
+
if (response.status === 204 || response.headers.get("Content-Length") === "0") {
|
|
3111
|
+
let emptyData;
|
|
3112
|
+
switch (parseAs) {
|
|
3113
|
+
case "arrayBuffer":
|
|
3114
|
+
case "blob":
|
|
3115
|
+
case "text":
|
|
3116
|
+
emptyData = await response[parseAs]();
|
|
3117
|
+
break;
|
|
3118
|
+
case "formData":
|
|
3119
|
+
emptyData = new FormData();
|
|
3120
|
+
break;
|
|
3121
|
+
case "stream":
|
|
3122
|
+
emptyData = response.body;
|
|
3123
|
+
break;
|
|
3124
|
+
case "json":
|
|
3125
|
+
default:
|
|
3126
|
+
emptyData = {};
|
|
3127
|
+
break;
|
|
3128
|
+
}
|
|
3129
|
+
return opts.responseStyle === "data" ? emptyData : {
|
|
3130
|
+
data: emptyData,
|
|
3131
|
+
...result
|
|
3132
|
+
};
|
|
3133
|
+
}
|
|
3134
|
+
let data;
|
|
3135
|
+
switch (parseAs) {
|
|
3136
|
+
case "arrayBuffer":
|
|
3137
|
+
case "blob":
|
|
3138
|
+
case "formData":
|
|
3139
|
+
case "text":
|
|
3140
|
+
data = await response[parseAs]();
|
|
3141
|
+
break;
|
|
3142
|
+
case "json": {
|
|
3143
|
+
const text = await response.text();
|
|
3144
|
+
data = text ? JSON.parse(text) : {};
|
|
3145
|
+
break;
|
|
3146
|
+
}
|
|
3147
|
+
case "stream":
|
|
3148
|
+
return opts.responseStyle === "data" ? response.body : {
|
|
3149
|
+
data: response.body,
|
|
3150
|
+
...result
|
|
3151
|
+
};
|
|
3152
|
+
}
|
|
3153
|
+
if (parseAs === "json") {
|
|
3154
|
+
if (opts.responseValidator) {
|
|
3155
|
+
await opts.responseValidator(data);
|
|
3156
|
+
}
|
|
3157
|
+
if (opts.responseTransformer) {
|
|
3158
|
+
data = await opts.responseTransformer(data);
|
|
3159
|
+
}
|
|
3160
|
+
}
|
|
3161
|
+
return opts.responseStyle === "data" ? data : {
|
|
3162
|
+
data,
|
|
3163
|
+
...result
|
|
3164
|
+
};
|
|
3165
|
+
}
|
|
3166
|
+
const textError = await response.text();
|
|
3167
|
+
let jsonError;
|
|
3168
|
+
try {
|
|
3169
|
+
jsonError = JSON.parse(textError);
|
|
3170
|
+
} catch {
|
|
3171
|
+
}
|
|
3172
|
+
throw jsonError ?? textError;
|
|
3173
|
+
} catch (error) {
|
|
3174
|
+
let finalError = error;
|
|
3175
|
+
for (const fn of interceptors.error.fns) {
|
|
3176
|
+
if (fn) {
|
|
3177
|
+
finalError = await fn(finalError, response, request2, options);
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
finalError = finalError || {};
|
|
3181
|
+
if (throwOnError) {
|
|
3182
|
+
throw finalError;
|
|
3183
|
+
}
|
|
3184
|
+
return responseStyle === "data" ? void 0 : {
|
|
3185
|
+
error: finalError,
|
|
3186
|
+
request: request2,
|
|
3187
|
+
response
|
|
3188
|
+
};
|
|
3189
|
+
}
|
|
3190
|
+
};
|
|
3191
|
+
const makeMethodFn = (method) => (options) => request({ ...options, method });
|
|
3192
|
+
const makeSseFn = (method) => async (options) => {
|
|
3193
|
+
const { opts, url } = await beforeRequest(options);
|
|
3194
|
+
return createSseClient({
|
|
3195
|
+
...opts,
|
|
3196
|
+
body: opts.body,
|
|
3197
|
+
method,
|
|
3198
|
+
onRequest: async (url2, init) => {
|
|
3199
|
+
let request2 = new Request(url2, init);
|
|
3200
|
+
for (const fn of interceptors.request.fns) {
|
|
3201
|
+
if (fn) {
|
|
3202
|
+
request2 = await fn(request2, opts);
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
return request2;
|
|
3206
|
+
},
|
|
3207
|
+
serializedBody: getValidRequestBody(opts),
|
|
3208
|
+
url
|
|
3209
|
+
});
|
|
3210
|
+
};
|
|
3211
|
+
const _buildUrl = (options) => buildUrl({ ..._config, ...options });
|
|
3212
|
+
return {
|
|
3213
|
+
buildUrl: _buildUrl,
|
|
3214
|
+
connect: makeMethodFn("CONNECT"),
|
|
3215
|
+
delete: makeMethodFn("DELETE"),
|
|
3216
|
+
get: makeMethodFn("GET"),
|
|
3217
|
+
getConfig,
|
|
3218
|
+
head: makeMethodFn("HEAD"),
|
|
3219
|
+
interceptors,
|
|
3220
|
+
options: makeMethodFn("OPTIONS"),
|
|
3221
|
+
patch: makeMethodFn("PATCH"),
|
|
3222
|
+
post: makeMethodFn("POST"),
|
|
3223
|
+
put: makeMethodFn("PUT"),
|
|
3224
|
+
request,
|
|
3225
|
+
setConfig,
|
|
3226
|
+
sse: {
|
|
3227
|
+
connect: makeSseFn("CONNECT"),
|
|
3228
|
+
delete: makeSseFn("DELETE"),
|
|
3229
|
+
get: makeSseFn("GET"),
|
|
3230
|
+
head: makeSseFn("HEAD"),
|
|
3231
|
+
options: makeSseFn("OPTIONS"),
|
|
3232
|
+
patch: makeSseFn("PATCH"),
|
|
3233
|
+
post: makeSseFn("POST"),
|
|
3234
|
+
put: makeSseFn("PUT"),
|
|
3235
|
+
trace: makeSseFn("TRACE")
|
|
3236
|
+
},
|
|
3237
|
+
trace: makeMethodFn("TRACE")
|
|
3238
|
+
};
|
|
3239
|
+
};
|
|
3240
|
+
|
|
3241
|
+
// ../sdk/src/generated/sdk.gen.ts
|
|
3242
|
+
var sdk_gen_exports = {};
|
|
3243
|
+
__export(sdk_gen_exports, {
|
|
3244
|
+
createAlert: () => createAlert,
|
|
3245
|
+
createApiKey: () => createApiKey,
|
|
3246
|
+
createChannel: () => createChannel,
|
|
3247
|
+
createKeyword: () => createKeyword,
|
|
3248
|
+
createSegment: () => createSegment,
|
|
3249
|
+
deleteAlert: () => deleteAlert,
|
|
3250
|
+
deleteChannel: () => deleteChannel,
|
|
3251
|
+
deleteKeyword: () => deleteKeyword,
|
|
3252
|
+
deleteSegment: () => deleteSegment,
|
|
3253
|
+
exportMentionsCsv: () => exportMentionsCsv,
|
|
3254
|
+
exportPeopleCsv: () => exportPeopleCsv,
|
|
3255
|
+
getAlert: () => getAlert,
|
|
3256
|
+
getAnalyticsBreakdown: () => getAnalyticsBreakdown,
|
|
3257
|
+
getAnalyticsSeries: () => getAnalyticsSeries,
|
|
3258
|
+
getAnalyticsSummary: () => getAnalyticsSummary,
|
|
3259
|
+
getChannel: () => getChannel,
|
|
3260
|
+
getCompany: () => getCompany,
|
|
3261
|
+
getHealth: () => getHealth,
|
|
3262
|
+
getKeyword: () => getKeyword,
|
|
3263
|
+
getMention: () => getMention,
|
|
3264
|
+
getPerson: () => getPerson,
|
|
3265
|
+
getSegment: () => getSegment,
|
|
3266
|
+
getShareOfVoice: () => getShareOfVoice,
|
|
3267
|
+
listAlerts: () => listAlerts,
|
|
3268
|
+
listApiKeys: () => listApiKeys,
|
|
3269
|
+
listChannelDeliveries: () => listChannelDeliveries,
|
|
3270
|
+
listChannels: () => listChannels,
|
|
3271
|
+
listKeywords: () => listKeywords,
|
|
3272
|
+
listPeople: () => listPeople,
|
|
3273
|
+
listSegments: () => listSegments,
|
|
3274
|
+
mergePeople: () => mergePeople,
|
|
3275
|
+
revokeApiKey: () => revokeApiKey,
|
|
3276
|
+
rotateWebhookSecret: () => rotateWebhookSecret,
|
|
3277
|
+
runAlertDigest: () => runAlertDigest,
|
|
3278
|
+
searchMentions: () => searchMentions,
|
|
3279
|
+
splitPerson: () => splitPerson,
|
|
3280
|
+
testAlert: () => testAlert,
|
|
3281
|
+
testChannel: () => testChannel,
|
|
3282
|
+
updateAlert: () => updateAlert,
|
|
3283
|
+
updateChannel: () => updateChannel,
|
|
3284
|
+
updateCompany: () => updateCompany,
|
|
3285
|
+
updateKeyword: () => updateKeyword,
|
|
3286
|
+
updateMention: () => updateMention,
|
|
3287
|
+
updatePerson: () => updatePerson,
|
|
3288
|
+
updateSegment: () => updateSegment
|
|
3289
|
+
});
|
|
3290
|
+
|
|
3291
|
+
// ../sdk/src/generated/client.gen.ts
|
|
3292
|
+
var client = createClient(createConfig({ baseUrl: "https://api.mentio.dev" }));
|
|
3293
|
+
|
|
3294
|
+
// ../sdk/src/generated/sdk.gen.ts
|
|
3295
|
+
var getHealth = (options) => (options?.client ?? client).get({ url: "/v1/health", ...options });
|
|
3296
|
+
var listKeywords = (options) => (options?.client ?? client).get({
|
|
3297
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3298
|
+
url: "/v1/keywords",
|
|
3299
|
+
...options
|
|
3300
|
+
});
|
|
3301
|
+
var createKeyword = (options) => (options.client ?? client).post({
|
|
3302
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3303
|
+
url: "/v1/keywords",
|
|
3304
|
+
...options,
|
|
3305
|
+
headers: {
|
|
3306
|
+
"Content-Type": "application/json",
|
|
3307
|
+
...options.headers
|
|
3308
|
+
}
|
|
3309
|
+
});
|
|
3310
|
+
var deleteKeyword = (options) => (options.client ?? client).delete({
|
|
3311
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3312
|
+
url: "/v1/keywords/{id}",
|
|
3313
|
+
...options
|
|
3314
|
+
});
|
|
3315
|
+
var getKeyword = (options) => (options.client ?? client).get({
|
|
3316
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3317
|
+
url: "/v1/keywords/{id}",
|
|
3318
|
+
...options
|
|
3319
|
+
});
|
|
3320
|
+
var updateKeyword = (options) => (options.client ?? client).patch({
|
|
3321
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3322
|
+
url: "/v1/keywords/{id}",
|
|
3323
|
+
...options,
|
|
3324
|
+
headers: {
|
|
3325
|
+
"Content-Type": "application/json",
|
|
3326
|
+
...options.headers
|
|
3327
|
+
}
|
|
3328
|
+
});
|
|
3329
|
+
var getMention = (options) => (options.client ?? client).get({
|
|
3330
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3331
|
+
url: "/v1/mentions/{id}",
|
|
3332
|
+
...options
|
|
3333
|
+
});
|
|
3334
|
+
var updateMention = (options) => (options.client ?? client).patch({
|
|
3335
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3336
|
+
url: "/v1/mentions/{id}",
|
|
3337
|
+
...options,
|
|
3338
|
+
headers: {
|
|
3339
|
+
"Content-Type": "application/json",
|
|
3340
|
+
...options.headers
|
|
3341
|
+
}
|
|
3342
|
+
});
|
|
3343
|
+
var searchMentions = (options) => (options?.client ?? client).get({
|
|
3344
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3345
|
+
url: "/v1/mentions",
|
|
3346
|
+
...options
|
|
3347
|
+
});
|
|
3348
|
+
var exportMentionsCsv = (options) => (options?.client ?? client).get({
|
|
3349
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3350
|
+
url: "/v1/mentions/export.csv",
|
|
3351
|
+
...options
|
|
3352
|
+
});
|
|
3353
|
+
var exportPeopleCsv = (options) => (options?.client ?? client).get({
|
|
3354
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3355
|
+
url: "/v1/people/export.csv",
|
|
3356
|
+
...options
|
|
3357
|
+
});
|
|
3358
|
+
var listPeople = (options) => (options?.client ?? client).get({
|
|
3359
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3360
|
+
url: "/v1/people",
|
|
3361
|
+
...options
|
|
3362
|
+
});
|
|
3363
|
+
var getPerson = (options) => (options.client ?? client).get({
|
|
3364
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3365
|
+
url: "/v1/people/{id}",
|
|
3366
|
+
...options
|
|
3367
|
+
});
|
|
3368
|
+
var updatePerson = (options) => (options.client ?? client).patch({
|
|
3369
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3370
|
+
url: "/v1/people/{id}",
|
|
3371
|
+
...options,
|
|
3372
|
+
headers: {
|
|
3373
|
+
"Content-Type": "application/json",
|
|
3374
|
+
...options.headers
|
|
3375
|
+
}
|
|
3376
|
+
});
|
|
3377
|
+
var mergePeople = (options) => (options.client ?? client).post({
|
|
3378
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3379
|
+
url: "/v1/people/{id}/merge",
|
|
3380
|
+
...options,
|
|
3381
|
+
headers: {
|
|
3382
|
+
"Content-Type": "application/json",
|
|
3383
|
+
...options.headers
|
|
3384
|
+
}
|
|
3385
|
+
});
|
|
3386
|
+
var splitPerson = (options) => (options.client ?? client).post({
|
|
3387
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3388
|
+
url: "/v1/people/{id}/split",
|
|
3389
|
+
...options
|
|
3390
|
+
});
|
|
3391
|
+
var listSegments = (options) => (options?.client ?? client).get({
|
|
3392
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3393
|
+
url: "/v1/segments",
|
|
3394
|
+
...options
|
|
3395
|
+
});
|
|
3396
|
+
var createSegment = (options) => (options.client ?? client).post({
|
|
3397
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3398
|
+
url: "/v1/segments",
|
|
3399
|
+
...options,
|
|
3400
|
+
headers: {
|
|
3401
|
+
"Content-Type": "application/json",
|
|
3402
|
+
...options.headers
|
|
3403
|
+
}
|
|
3404
|
+
});
|
|
3405
|
+
var deleteSegment = (options) => (options.client ?? client).delete({
|
|
3406
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3407
|
+
url: "/v1/segments/{id}",
|
|
3408
|
+
...options
|
|
3409
|
+
});
|
|
3410
|
+
var getSegment = (options) => (options.client ?? client).get({
|
|
3411
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3412
|
+
url: "/v1/segments/{id}",
|
|
3413
|
+
...options
|
|
3414
|
+
});
|
|
3415
|
+
var updateSegment = (options) => (options.client ?? client).patch({
|
|
3416
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3417
|
+
url: "/v1/segments/{id}",
|
|
3418
|
+
...options,
|
|
3419
|
+
headers: {
|
|
3420
|
+
"Content-Type": "application/json",
|
|
3421
|
+
...options.headers
|
|
3422
|
+
}
|
|
3423
|
+
});
|
|
3424
|
+
var getCompany = (options) => (options?.client ?? client).get({
|
|
3425
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3426
|
+
url: "/v1/company",
|
|
3427
|
+
...options
|
|
3428
|
+
});
|
|
3429
|
+
var updateCompany = (options) => (options.client ?? client).patch({
|
|
3430
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3431
|
+
url: "/v1/company",
|
|
3432
|
+
...options,
|
|
3433
|
+
headers: {
|
|
3434
|
+
"Content-Type": "application/json",
|
|
3435
|
+
...options.headers
|
|
3436
|
+
}
|
|
3437
|
+
});
|
|
3438
|
+
var listApiKeys = (options) => (options?.client ?? client).get({
|
|
3439
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3440
|
+
url: "/v1/api-keys",
|
|
3441
|
+
...options
|
|
3442
|
+
});
|
|
3443
|
+
var createApiKey = (options) => (options.client ?? client).post({
|
|
3444
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3445
|
+
url: "/v1/api-keys",
|
|
3446
|
+
...options,
|
|
3447
|
+
headers: {
|
|
3448
|
+
"Content-Type": "application/json",
|
|
3449
|
+
...options.headers
|
|
3450
|
+
}
|
|
3451
|
+
});
|
|
3452
|
+
var revokeApiKey = (options) => (options.client ?? client).delete({
|
|
3453
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3454
|
+
url: "/v1/api-keys/{id}",
|
|
3455
|
+
...options
|
|
3456
|
+
});
|
|
3457
|
+
var deleteAlert = (options) => (options.client ?? client).delete({
|
|
3458
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3459
|
+
url: "/v1/alerts/{id}",
|
|
3460
|
+
...options
|
|
3461
|
+
});
|
|
3462
|
+
var getAlert = (options) => (options.client ?? client).get({
|
|
3463
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3464
|
+
url: "/v1/alerts/{id}",
|
|
3465
|
+
...options
|
|
3466
|
+
});
|
|
3467
|
+
var updateAlert = (options) => (options.client ?? client).patch({
|
|
3468
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3469
|
+
url: "/v1/alerts/{id}",
|
|
3470
|
+
...options,
|
|
3471
|
+
headers: {
|
|
3472
|
+
"Content-Type": "application/json",
|
|
3473
|
+
...options.headers
|
|
3474
|
+
}
|
|
3475
|
+
});
|
|
3476
|
+
var listAlerts = (options) => (options?.client ?? client).get({
|
|
3477
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3478
|
+
url: "/v1/alerts",
|
|
3479
|
+
...options
|
|
3480
|
+
});
|
|
3481
|
+
var createAlert = (options) => (options.client ?? client).post({
|
|
3482
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3483
|
+
url: "/v1/alerts",
|
|
3484
|
+
...options,
|
|
3485
|
+
headers: {
|
|
3486
|
+
"Content-Type": "application/json",
|
|
3487
|
+
...options.headers
|
|
3488
|
+
}
|
|
3489
|
+
});
|
|
3490
|
+
var testAlert = (options) => (options.client ?? client).post({
|
|
3491
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3492
|
+
url: "/v1/alerts/{id}/test",
|
|
3493
|
+
...options
|
|
3494
|
+
});
|
|
3495
|
+
var runAlertDigest = (options) => (options.client ?? client).post({
|
|
3496
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3497
|
+
url: "/v1/alerts/{id}/run",
|
|
3498
|
+
...options
|
|
3499
|
+
});
|
|
3500
|
+
var getAnalyticsSummary = (options) => (options?.client ?? client).get({
|
|
3501
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3502
|
+
url: "/v1/analytics/summary",
|
|
3503
|
+
...options
|
|
3504
|
+
});
|
|
3505
|
+
var getAnalyticsSeries = (options) => (options?.client ?? client).get({
|
|
3506
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3507
|
+
url: "/v1/analytics/series",
|
|
3508
|
+
...options
|
|
3509
|
+
});
|
|
3510
|
+
var getAnalyticsBreakdown = (options) => (options.client ?? client).get({
|
|
3511
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3512
|
+
url: "/v1/analytics/breakdown",
|
|
3513
|
+
...options
|
|
3514
|
+
});
|
|
3515
|
+
var getShareOfVoice = (options) => (options?.client ?? client).get({
|
|
3516
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3517
|
+
url: "/v1/analytics/share-of-voice",
|
|
3518
|
+
...options
|
|
3519
|
+
});
|
|
3520
|
+
var deleteChannel = (options) => (options.client ?? client).delete({
|
|
3521
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3522
|
+
url: "/v1/channels/{id}",
|
|
3523
|
+
...options
|
|
3524
|
+
});
|
|
3525
|
+
var getChannel = (options) => (options.client ?? client).get({
|
|
3526
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3527
|
+
url: "/v1/channels/{id}",
|
|
3528
|
+
...options
|
|
3529
|
+
});
|
|
3530
|
+
var updateChannel = (options) => (options.client ?? client).patch({
|
|
3531
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3532
|
+
url: "/v1/channels/{id}",
|
|
3533
|
+
...options,
|
|
3534
|
+
headers: {
|
|
3535
|
+
"Content-Type": "application/json",
|
|
3536
|
+
...options.headers
|
|
3537
|
+
}
|
|
3538
|
+
});
|
|
3539
|
+
var testChannel = (options) => (options.client ?? client).post({
|
|
3540
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3541
|
+
url: "/v1/channels/{id}/test",
|
|
3542
|
+
...options
|
|
3543
|
+
});
|
|
3544
|
+
var rotateWebhookSecret = (options) => (options.client ?? client).post({
|
|
3545
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3546
|
+
url: "/v1/channels/{id}/rotate-secret",
|
|
3547
|
+
...options
|
|
3548
|
+
});
|
|
3549
|
+
var listChannelDeliveries = (options) => (options.client ?? client).get({
|
|
3550
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3551
|
+
url: "/v1/channels/{id}/deliveries",
|
|
3552
|
+
...options
|
|
3553
|
+
});
|
|
3554
|
+
var listChannels = (options) => (options?.client ?? client).get({
|
|
3555
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3556
|
+
url: "/v1/channels",
|
|
3557
|
+
...options
|
|
3558
|
+
});
|
|
3559
|
+
var createChannel = (options) => (options.client ?? client).post({
|
|
3560
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3561
|
+
url: "/v1/channels",
|
|
3562
|
+
...options,
|
|
3563
|
+
headers: {
|
|
3564
|
+
"Content-Type": "application/json",
|
|
3565
|
+
...options.headers
|
|
3566
|
+
}
|
|
3567
|
+
});
|
|
3568
|
+
|
|
3569
|
+
// ../sdk/src/index.ts
|
|
3570
|
+
var DEFAULT_BASE_URL = "https://api.mentio.dev";
|
|
3571
|
+
function createMentio(options) {
|
|
3572
|
+
const client2 = createClient(
|
|
3573
|
+
createConfig({
|
|
3574
|
+
baseUrl: (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, ""),
|
|
3575
|
+
auth: () => options.apiKey,
|
|
3576
|
+
...options.fetch ? { fetch: options.fetch } : {},
|
|
3577
|
+
...options.headers ? { headers: options.headers } : {}
|
|
3578
|
+
})
|
|
3579
|
+
);
|
|
3580
|
+
const bound = {};
|
|
3581
|
+
for (const [name, fn] of Object.entries(sdk_gen_exports)) {
|
|
3582
|
+
if (typeof fn !== "function") continue;
|
|
3583
|
+
const call = fn;
|
|
3584
|
+
bound[name] = (callOptions) => call({ ...callOptions, client: callOptions?.client ?? client2 });
|
|
3585
|
+
}
|
|
3586
|
+
return { ...bound, client: client2 };
|
|
3587
|
+
}
|
|
3588
|
+
|
|
3589
|
+
// src/run.ts
|
|
3590
|
+
function clientFor(settings, fetchImpl) {
|
|
3591
|
+
return createMentio({ apiKey: settings.apiKey ?? "", baseUrl: settings.apiUrl, ...fetchImpl ? { fetch: fetchImpl } : {} }).client;
|
|
3592
|
+
}
|
|
3593
|
+
var BEARER = [{ scheme: "bearer", type: "http" }];
|
|
3594
|
+
async function runOperation(client2, op, request) {
|
|
3595
|
+
const result = await client2.request({
|
|
3596
|
+
method: op.method,
|
|
3597
|
+
url: op.path,
|
|
3598
|
+
path: request.path,
|
|
3599
|
+
query: request.query,
|
|
3600
|
+
...request.body !== void 0 ? { body: request.body } : {},
|
|
3601
|
+
parseAs: op.response === "csv" ? "text" : "auto",
|
|
3602
|
+
security: BEARER,
|
|
3603
|
+
throwOnError: false
|
|
3604
|
+
});
|
|
3605
|
+
const status = result.response?.status ?? 0;
|
|
3606
|
+
if (result.error !== void 0) return { ok: false, status, value: result.error };
|
|
3607
|
+
if (!result.response) return { ok: false, status, value: void 0 };
|
|
3608
|
+
return { ok: result.response.ok, status, value: result.data ?? void 0 };
|
|
3609
|
+
}
|
|
3610
|
+
function errorEnvelope(outcome) {
|
|
3611
|
+
const value = outcome.value;
|
|
3612
|
+
if (value !== null && typeof value === "object" && "error" in value) {
|
|
3613
|
+
const inner = value.error;
|
|
3614
|
+
if (inner !== null && typeof inner === "object" && "code" in inner && "message" in inner) {
|
|
3615
|
+
return value;
|
|
3616
|
+
}
|
|
3617
|
+
}
|
|
3618
|
+
const message = typeof value === "string" && value.trim() !== "" ? value.trim().slice(0, 300) : `Request failed with status ${outcome.status}`;
|
|
3619
|
+
return { error: { code: `http_${outcome.status}`, message } };
|
|
3620
|
+
}
|
|
3621
|
+
|
|
3622
|
+
// src/watch.ts
|
|
3623
|
+
var SEEN_LIMIT = 5e3;
|
|
3624
|
+
var PAGE = 100;
|
|
3625
|
+
var newSeen = () => ({ ids: /* @__PURE__ */ new Set(), order: [] });
|
|
3626
|
+
function takeNew(seen, newestFirst) {
|
|
3627
|
+
const fresh = [];
|
|
3628
|
+
for (const item of newestFirst) {
|
|
3629
|
+
if (seen.ids.has(item.id)) continue;
|
|
3630
|
+
fresh.push(item);
|
|
3631
|
+
}
|
|
3632
|
+
for (const item of fresh) {
|
|
3633
|
+
seen.ids.add(item.id);
|
|
3634
|
+
seen.order.push(item.id);
|
|
3635
|
+
}
|
|
3636
|
+
while (seen.order.length > SEEN_LIMIT) {
|
|
3637
|
+
const oldest = seen.order.shift();
|
|
3638
|
+
if (oldest !== void 0) seen.ids.delete(oldest);
|
|
3639
|
+
}
|
|
3640
|
+
return fresh.reverse();
|
|
3641
|
+
}
|
|
3642
|
+
var defaultSleep = (ms, signal) => new Promise((resolve) => {
|
|
3643
|
+
if (signal.aborted) return resolve();
|
|
3644
|
+
const timer = setTimeout(resolve, ms);
|
|
3645
|
+
signal.addEventListener("abort", () => {
|
|
3646
|
+
clearTimeout(timer);
|
|
3647
|
+
resolve();
|
|
3648
|
+
});
|
|
3649
|
+
});
|
|
3650
|
+
async function watchMentions(options) {
|
|
3651
|
+
const sleep = options.sleep ?? defaultSleep;
|
|
3652
|
+
const seen = newSeen();
|
|
3653
|
+
let first = true;
|
|
3654
|
+
while (!options.signal.aborted) {
|
|
3655
|
+
const result = await options.client.request({
|
|
3656
|
+
method: "GET",
|
|
3657
|
+
url: "/v1/mentions",
|
|
3658
|
+
query: { ...options.query, sort: "newest", limit: PAGE },
|
|
3659
|
+
security: BEARER,
|
|
3660
|
+
throwOnError: false
|
|
3661
|
+
});
|
|
3662
|
+
if (result.error !== void 0 || !result.response?.ok) {
|
|
3663
|
+
options.warn(JSON.stringify({ error: result.error ?? { code: `http_${result.response?.status ?? 0}`, message: "poll failed" } }));
|
|
3664
|
+
} else {
|
|
3665
|
+
const page = result.data?.data ?? [];
|
|
3666
|
+
const fresh = takeNew(seen, page);
|
|
3667
|
+
if (!first || options.fromStart) for (const item of fresh) options.write(JSON.stringify(item));
|
|
3668
|
+
}
|
|
3669
|
+
first = false;
|
|
3670
|
+
await sleep(options.intervalMs, options.signal);
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
|
|
3674
|
+
// src/index.ts
|
|
3675
|
+
var program = new Command();
|
|
3676
|
+
var stdoutIsTty = () => Boolean(process.stdout.isTTY);
|
|
3677
|
+
function print(value, globals) {
|
|
3678
|
+
process.stdout.write(`${formatOutput(value, { pretty: globals.pretty ?? stdoutIsTty(), table: globals.table ?? false })}
|
|
3679
|
+
`);
|
|
3680
|
+
}
|
|
3681
|
+
function fail(envelope, code = 1) {
|
|
3682
|
+
process.stderr.write(`${JSON.stringify(envelope)}
|
|
3683
|
+
`);
|
|
3684
|
+
process.exit(code);
|
|
3685
|
+
}
|
|
3686
|
+
function settingsOrFail(globals, needsKey) {
|
|
3687
|
+
const settings = resolveSettings({ apiKey: globals.apiKey, apiUrl: globals.apiUrl });
|
|
3688
|
+
if (needsKey && !settings.apiKey) {
|
|
3689
|
+
fail({ error: { code: "no_api_key", message: "No API key. Run `mentio auth:set --key mk_live_...`, set MENTIO_API_KEY, or pass --api-key." } }, 2);
|
|
3690
|
+
}
|
|
3691
|
+
return settings;
|
|
3692
|
+
}
|
|
3693
|
+
function addFieldOption(command, field) {
|
|
3694
|
+
const option = new Option(`--${field.name} <value>`, flagHelp(field));
|
|
3695
|
+
if (field.enum && field.type !== "array") option.choices(field.nullable ? [...field.enum, "null"] : field.enum);
|
|
3696
|
+
command.addOption(option);
|
|
3697
|
+
}
|
|
3698
|
+
function registerOperation(op) {
|
|
3699
|
+
const name = commandName(op);
|
|
3700
|
+
const command = program.command(name).description(op.summary).summary(op.summary);
|
|
3701
|
+
if (op.description) command.addHelpText("after", `
|
|
3702
|
+
${op.description}
|
|
3703
|
+
`);
|
|
3704
|
+
for (const param of op.params.filter((p) => p.in === "path")) command.argument(`<${param.name}>`, param.description ?? "");
|
|
3705
|
+
for (const param of op.params.filter((p) => p.in === "query")) addFieldOption(command, param);
|
|
3706
|
+
if (op.body) {
|
|
3707
|
+
for (const field of op.body.fields) addFieldOption(command, field);
|
|
3708
|
+
command.option("--json <object>", 'The whole body as JSON; flags override its fields. "-" reads stdin.');
|
|
3709
|
+
}
|
|
3710
|
+
if (op.response === "csv") command.option("--out <file>", "Write the CSV to a file instead of stdout.");
|
|
3711
|
+
command.action(async (...args) => {
|
|
3712
|
+
const cmd = args[args.length - 1];
|
|
3713
|
+
const positional = args.slice(0, -2);
|
|
3714
|
+
const flags = cmd.opts();
|
|
3715
|
+
const globals = program.opts();
|
|
3716
|
+
try {
|
|
3717
|
+
let jsonBody = typeof flags.json === "string" ? flags.json : void 0;
|
|
3718
|
+
if (jsonBody === "-") jsonBody = await readStdin();
|
|
3719
|
+
const request = buildRequest(op, positional, flags, jsonBody);
|
|
3720
|
+
const settings = settingsOrFail(globals, op.operationId !== "getHealth");
|
|
3721
|
+
const outcome = await runOperation(clientFor(settings), op, request);
|
|
3722
|
+
if (!outcome.ok) fail(errorEnvelope(outcome));
|
|
3723
|
+
if (op.response === "csv") {
|
|
3724
|
+
const csv = typeof outcome.value === "string" ? outcome.value : "";
|
|
3725
|
+
if (typeof flags.out === "string") {
|
|
3726
|
+
writeFileSync2(flags.out, csv);
|
|
3727
|
+
print({ ok: true, file: flags.out, bytes: Buffer.byteLength(csv) }, globals);
|
|
3728
|
+
} else {
|
|
3729
|
+
process.stdout.write(csv);
|
|
3730
|
+
}
|
|
3731
|
+
return;
|
|
3732
|
+
}
|
|
3733
|
+
print(outcome.value === void 0 ? { ok: true, status: outcome.status } : outcome.value, globals);
|
|
3734
|
+
} catch (err) {
|
|
3735
|
+
if (err instanceof UsageError) fail({ error: { code: "usage", message: err.message } }, 2);
|
|
3736
|
+
throw err;
|
|
3737
|
+
}
|
|
3738
|
+
});
|
|
3739
|
+
}
|
|
3740
|
+
async function readStdin() {
|
|
3741
|
+
const chunks = [];
|
|
3742
|
+
for await (const chunk of process.stdin) chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
3743
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
3744
|
+
}
|
|
3745
|
+
function registerAuth() {
|
|
3746
|
+
program.command("auth:set").description("Store an API key (and optionally the API host) in ~/.mentio/config.json").requiredOption("--key <key>", "API key from the dashboard or POST /v1/api-keys (mk_live_...)").option("--url <url>", "API host for a self-hosted deployment").action((flags) => {
|
|
3747
|
+
const path = writeConfig({ apiKey: flags.key, ...flags.url ? { apiUrl: flags.url } : {} });
|
|
3748
|
+
print({ ok: true, file: path, key: keyPrefix(flags.key) }, program.opts());
|
|
3749
|
+
});
|
|
3750
|
+
program.command("auth:logout").description("Remove the stored API key").action(() => {
|
|
3751
|
+
const path = writeConfig({ apiKey: null });
|
|
3752
|
+
print({ ok: true, file: path }, program.opts());
|
|
3753
|
+
});
|
|
3754
|
+
program.command("auth:check").description("Verify the key: which workspace it belongs to and where it came from").action(async () => {
|
|
3755
|
+
const globals = program.opts();
|
|
3756
|
+
const settings = settingsOrFail(globals, true);
|
|
3757
|
+
const result = await clientFor(settings).request({ method: "GET", url: "/v1/company", security: BEARER, throwOnError: false });
|
|
3758
|
+
if (result.error !== void 0 || !result.response?.ok) {
|
|
3759
|
+
fail(errorEnvelope({ ok: false, status: result.response?.status ?? 0, value: result.error }));
|
|
3760
|
+
}
|
|
3761
|
+
const company = result.data;
|
|
3762
|
+
print({ ok: true, workspace: company?.name ?? null, key: keyPrefix(settings.apiKey ?? ""), source: settings.source, apiUrl: settings.apiUrl }, globals);
|
|
3763
|
+
});
|
|
3764
|
+
}
|
|
3765
|
+
function registerWatch() {
|
|
3766
|
+
const search = OPERATIONS.find((op) => op.operationId === "searchMentions");
|
|
3767
|
+
if (!search) return;
|
|
3768
|
+
const command = program.command("mentions:watch").description("Follow the feed: print each new mention as one JSON line (tail -f for mentions)").option("--interval <seconds>", "Seconds between polls", "30").option("--from-start", "Print the current newest page first instead of only what arrives next");
|
|
3769
|
+
const skip = /* @__PURE__ */ new Set(["cursor", "limit", "sort", "since", "until"]);
|
|
3770
|
+
const filters = search.params.filter((p) => p.in === "query" && !skip.has(p.name));
|
|
3771
|
+
for (const param of filters) addFieldOption(command, param);
|
|
3772
|
+
command.action(async (flags) => {
|
|
3773
|
+
const globals = program.opts();
|
|
3774
|
+
const settings = settingsOrFail(globals, true);
|
|
3775
|
+
const query = {};
|
|
3776
|
+
try {
|
|
3777
|
+
for (const param of filters) {
|
|
3778
|
+
const raw = flags[param.name];
|
|
3779
|
+
if (raw === void 0) continue;
|
|
3780
|
+
const value = coerce(param, String(raw));
|
|
3781
|
+
if (value !== null && typeof value !== "object") query[param.name] = value;
|
|
3782
|
+
}
|
|
3783
|
+
} catch (err) {
|
|
3784
|
+
if (err instanceof UsageError) fail({ error: { code: "usage", message: err.message } }, 2);
|
|
3785
|
+
throw err;
|
|
3786
|
+
}
|
|
3787
|
+
const seconds = Number(flags.interval);
|
|
3788
|
+
if (!Number.isFinite(seconds) || seconds < 5) fail({ error: { code: "usage", message: "--interval must be at least 5 seconds" } }, 2);
|
|
3789
|
+
const controller = new AbortController();
|
|
3790
|
+
process.on("SIGINT", () => controller.abort());
|
|
3791
|
+
process.on("SIGTERM", () => controller.abort());
|
|
3792
|
+
await watchMentions({
|
|
3793
|
+
client: clientFor(settings),
|
|
3794
|
+
query,
|
|
3795
|
+
intervalMs: seconds * 1e3,
|
|
3796
|
+
fromStart: flags.fromStart === true,
|
|
3797
|
+
write: (line) => process.stdout.write(`${line}
|
|
3798
|
+
`),
|
|
3799
|
+
warn: (line) => process.stderr.write(`${line}
|
|
3800
|
+
`),
|
|
3801
|
+
signal: controller.signal
|
|
3802
|
+
});
|
|
3803
|
+
});
|
|
3804
|
+
}
|
|
3805
|
+
function registerMcp() {
|
|
3806
|
+
program.command("mcp:config").description("Print the MCP client configuration for the Mentio MCP server, key included").addOption(new Option("--client <kind>", "Which client to print for").choices(["claude", "cursor", "vscode", "generic"]).default("claude")).option("--url <url>", "MCP server URL", DEFAULT_MCP_URL).action((flags) => {
|
|
3807
|
+
const globals = program.opts();
|
|
3808
|
+
const settings = resolveSettings({ apiKey: globals.apiKey, apiUrl: globals.apiUrl });
|
|
3809
|
+
const key = settings.apiKey ?? "mk_live_...";
|
|
3810
|
+
if (!settings.apiKey) process.stderr.write("No API key configured; printing a placeholder. Run `mentio auth:set --key ...` first.\n");
|
|
3811
|
+
process.stdout.write(`${mcpConfig(flags.client, flags.url, key)}
|
|
3812
|
+
`);
|
|
3813
|
+
});
|
|
3814
|
+
}
|
|
3815
|
+
program.name("mentio").description("Command line for the Mentio API. Commands are noun:verb; every endpoint has one.").version(package_default.version, "-V, --version").option("--api-key <key>", "API key (overrides MENTIO_API_KEY and the stored key)").option("--api-url <url>", "API host (overrides MENTIO_API_URL and the stored host)").option("--pretty", "Indent JSON output (the default on a terminal)").option("--table", "Render lists as a table").showHelpAfterError("(run with --help for usage)").configureHelp({ sortSubcommands: true });
|
|
3816
|
+
registerAuth();
|
|
3817
|
+
for (const op of OPERATIONS) registerOperation(op);
|
|
3818
|
+
registerWatch();
|
|
3819
|
+
registerMcp();
|
|
3820
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
3821
|
+
fail({ error: { code: "internal_error", message: err instanceof Error ? err.message : String(err) } });
|
|
3822
|
+
});
|
|
3823
|
+
//# sourceMappingURL=index.js.map
|