@chatlychat/sdk-node 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,111 @@
1
+ /**
2
+ * `@chatlychat/sdk-node` — the official Node.js SDK for the Chatly API.
3
+ *
4
+ * Authenticate with a workspace API key (`ck_…`) from server-side code. This
5
+ * is NOT the browser SDK: the key is a bearer credential for the whole
6
+ * workspace and must never be shipped to a browser. For in-page work use
7
+ * `@chatlychat/sdk-js`.
8
+ *
9
+ * The route surface is `packages/sdk-spec/surface.json`, which all ten Chatly
10
+ * SDKs implement; the behavioural contract is `packages/sdk-spec/CONTRACT.md`.
11
+ */
12
+ import { billingResource, channelsResource, contactsResource, conversationsResource, eventsResource, kbResource, macrosResource, reportsResource, searchResource, ticketsResource, webhooksResource, workspaceResource } from './resources.js';
13
+ import { Transport, type Query, type TransportOptions } from './transport.js';
14
+ export type ClientOptions = TransportOptions;
15
+ export { ChatlyError, ChatlyApiError, ChatlyAuthenticationError, ChatlyPermissionError, ChatlyNotFoundError, ChatlyConflictError, ChatlyValidationError, ChatlyRateLimitError, ChatlyServerError, ChatlyTransportError, } from './errors.js';
16
+ export { DEFAULT_API_URL, DEFAULT_RETRY, SDK_VERSION, type Query, type RetryPolicy } from './transport.js';
17
+ export { autoPaginate, type Page, type PageQuery } from './pagination.js';
18
+ export { verifyWebhookSignature, WEBHOOK_SIGNATURE_TOLERANCE_SECONDS, type VerifyWebhookSignatureInput, } from './webhooks.js';
19
+ export { chatlyIdentityHash } from './identity.js';
20
+ export type { AgentHandlingInput, ContactInput, EventListQuery, MergeContactInput, MergeTicketsInput, MessageInput, ScheduleMessageInput, UnsubscribeContactInput, TrackEventInput, Unmodelled, } from './resources.js';
21
+ /**
22
+ * Reaction payload.
23
+ *
24
+ * Declared here rather than imported from `@livechat/shared`: this package is
25
+ * published to consumers who must not have to install monorepo internals, so
26
+ * it stays dependency-free by design. The shape mirrors
27
+ * `@livechat/shared/reactions` and is covered by the API's own contract tests.
28
+ */
29
+ export interface MessageReactions {
30
+ readonly messageId: string;
31
+ readonly entries: ReadonlyArray<{
32
+ emoji: string;
33
+ count: number;
34
+ reacted: boolean;
35
+ }>;
36
+ }
37
+ /**
38
+ * Widget behaviour config. Structural, for the same reason as above — pass a
39
+ * plain object; the API validates it against the authoritative zod schema and
40
+ * rejects anything malformed.
41
+ */
42
+ export type WidgetFeatureConfig = Record<string, unknown>;
43
+ export declare class ChatlyClient {
44
+ private readonly transport;
45
+ readonly contacts: ReturnType<typeof contactsResource>;
46
+ readonly conversations: ReturnType<typeof conversationsResource>;
47
+ readonly tickets: ReturnType<typeof ticketsResource>;
48
+ readonly macros: ReturnType<typeof macrosResource>;
49
+ readonly kb: ReturnType<typeof kbResource>;
50
+ readonly search: ReturnType<typeof searchResource>;
51
+ readonly events: ReturnType<typeof eventsResource>;
52
+ readonly webhooks: ReturnType<typeof webhooksResource>;
53
+ readonly reports: ReturnType<typeof reportsResource>;
54
+ readonly channels: ReturnType<typeof channelsResource>;
55
+ readonly billing: ReturnType<typeof billingResource>;
56
+ readonly workspace: ReturnType<typeof workspaceResource>;
57
+ constructor(opts: ClientOptions);
58
+ constructor(transport: Transport);
59
+ /**
60
+ * Pin a specific `Idempotency-Key` for one or more upcoming writes.
61
+ *
62
+ * Returns a derived client (the original is unchanged). Use this when you
63
+ * want to retry the *same* logical operation across process boundaries: the
64
+ * API treats two writes with the same key + same body as a single accepted
65
+ * operation and replays the cached response. Two writes with the same key
66
+ * but a different body return HTTP 409.
67
+ *
68
+ * You do not need this for ordinary retries — the SDK already reuses one key
69
+ * across its own attempts of a single call.
70
+ *
71
+ * ```ts
72
+ * const key = crypto.randomUUID();
73
+ * for (let attempt = 0; attempt < 3; attempt++) {
74
+ * try {
75
+ * return await chatly.withIdempotencyKey(key).contacts.upsert(body);
76
+ * } catch (err) { ...backoff }
77
+ * }
78
+ * ```
79
+ */
80
+ withIdempotencyKey(key: string): ChatlyClient;
81
+ /**
82
+ * Describe the credential this client is using: which workspace it belongs
83
+ * to and which scopes it was granted.
84
+ *
85
+ * `GET /v1/api-keys/whoami` is deliberately the ONLY route on the api-keys
86
+ * controller that accepts an API key (managing keys with a key is a
87
+ * privilege-escalation shape). It is the call to make first: it turns a
88
+ * mis-scoped key into an obvious error at integration time rather than a
89
+ * 403 from an unrelated endpoint later.
90
+ *
91
+ * It was reachable over raw HTTP but appeared in no SDK and no doc, so
92
+ * there was no way for an integrator to discover it.
93
+ */
94
+ whoami(): Promise<{
95
+ workspaceId: string;
96
+ scopes: readonly string[];
97
+ }>;
98
+ /**
99
+ * Call any route, including the 85 key-accessible ones with no typed method
100
+ * here. Goes through the same auth, idempotency, retry and error handling.
101
+ *
102
+ * ```ts
103
+ * const flags = await chatly.request<Flags>('GET', '/v1/feature-flags');
104
+ * ```
105
+ */
106
+ request<T>(method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE', path: string, options?: {
107
+ query?: Query;
108
+ body?: unknown;
109
+ }): Promise<T>;
110
+ }
111
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,116 @@
1
+ /**
2
+ * `@chatlychat/sdk-node` — the official Node.js SDK for the Chatly API.
3
+ *
4
+ * Authenticate with a workspace API key (`ck_…`) from server-side code. This
5
+ * is NOT the browser SDK: the key is a bearer credential for the whole
6
+ * workspace and must never be shipped to a browser. For in-page work use
7
+ * `@chatlychat/sdk-js`.
8
+ *
9
+ * The route surface is `packages/sdk-spec/surface.json`, which all ten Chatly
10
+ * SDKs implement; the behavioural contract is `packages/sdk-spec/CONTRACT.md`.
11
+ */
12
+ import { billingResource, channelsResource, contactsResource, conversationsResource, eventsResource, kbResource, macrosResource, reportsResource, searchResource, ticketsResource, webhooksResource, workspaceResource, } from './resources.js';
13
+ import { Transport } from './transport.js';
14
+ export { ChatlyError, ChatlyApiError, ChatlyAuthenticationError, ChatlyPermissionError, ChatlyNotFoundError, ChatlyConflictError, ChatlyValidationError, ChatlyRateLimitError, ChatlyServerError, ChatlyTransportError, } from './errors.js';
15
+ export { DEFAULT_API_URL, DEFAULT_RETRY, SDK_VERSION } from './transport.js';
16
+ export { autoPaginate } from './pagination.js';
17
+ export { verifyWebhookSignature, WEBHOOK_SIGNATURE_TOLERANCE_SECONDS, } from './webhooks.js';
18
+ export { chatlyIdentityHash } from './identity.js';
19
+ export class ChatlyClient {
20
+ transport;
21
+ contacts;
22
+ conversations;
23
+ tickets;
24
+ macros;
25
+ kb;
26
+ search;
27
+ events;
28
+ webhooks;
29
+ reports;
30
+ channels;
31
+ billing;
32
+ workspace;
33
+ constructor(optsOrTransport) {
34
+ /*
35
+ * Every namespace is built from THIS instance's transport.
36
+ *
37
+ * The previous design hand-wrote a `derive` clone that re-bound each
38
+ * namespace one by one, and forgot `search` — so a client returned by
39
+ * `withIdempotencyKey` had search methods still closed over the PARENT's
40
+ * dispatch. Harmless while both were reads against the same base URL, and
41
+ * a live bug the moment anything on `search` became a write. Building
42
+ * namespaces in the constructor from one transport makes the class of bug
43
+ * unreachable rather than tested for.
44
+ */
45
+ this.transport =
46
+ optsOrTransport instanceof Transport ? optsOrTransport : new Transport(optsOrTransport);
47
+ const t = this.transport;
48
+ this.contacts = contactsResource(t);
49
+ this.conversations = conversationsResource(t);
50
+ this.tickets = ticketsResource(t);
51
+ this.macros = macrosResource(t);
52
+ this.kb = kbResource(t);
53
+ this.search = searchResource(t);
54
+ this.events = eventsResource(t);
55
+ this.webhooks = webhooksResource(t);
56
+ this.reports = reportsResource(t);
57
+ this.channels = channelsResource(t);
58
+ this.billing = billingResource(t);
59
+ this.workspace = workspaceResource(t);
60
+ }
61
+ /**
62
+ * Pin a specific `Idempotency-Key` for one or more upcoming writes.
63
+ *
64
+ * Returns a derived client (the original is unchanged). Use this when you
65
+ * want to retry the *same* logical operation across process boundaries: the
66
+ * API treats two writes with the same key + same body as a single accepted
67
+ * operation and replays the cached response. Two writes with the same key
68
+ * but a different body return HTTP 409.
69
+ *
70
+ * You do not need this for ordinary retries — the SDK already reuses one key
71
+ * across its own attempts of a single call.
72
+ *
73
+ * ```ts
74
+ * const key = crypto.randomUUID();
75
+ * for (let attempt = 0; attempt < 3; attempt++) {
76
+ * try {
77
+ * return await chatly.withIdempotencyKey(key).contacts.upsert(body);
78
+ * } catch (err) { ...backoff }
79
+ * }
80
+ * ```
81
+ */
82
+ withIdempotencyKey(key) {
83
+ if (typeof key !== 'string' || key.length === 0) {
84
+ throw new TypeError('withIdempotencyKey: key must be a non-empty string');
85
+ }
86
+ return new ChatlyClient(this.transport.withPinnedKey(key));
87
+ }
88
+ /**
89
+ * Describe the credential this client is using: which workspace it belongs
90
+ * to and which scopes it was granted.
91
+ *
92
+ * `GET /v1/api-keys/whoami` is deliberately the ONLY route on the api-keys
93
+ * controller that accepts an API key (managing keys with a key is a
94
+ * privilege-escalation shape). It is the call to make first: it turns a
95
+ * mis-scoped key into an obvious error at integration time rather than a
96
+ * 403 from an unrelated endpoint later.
97
+ *
98
+ * It was reachable over raw HTTP but appeared in no SDK and no doc, so
99
+ * there was no way for an integrator to discover it.
100
+ */
101
+ async whoami() {
102
+ return this.transport.get('/v1/api-keys/whoami');
103
+ }
104
+ /**
105
+ * Call any route, including the 85 key-accessible ones with no typed method
106
+ * here. Goes through the same auth, idempotency, retry and error handling.
107
+ *
108
+ * ```ts
109
+ * const flags = await chatly.request<Flags>('GET', '/v1/feature-flags');
110
+ * ```
111
+ */
112
+ async request(method, path, options = {}) {
113
+ return this.transport.send(method, path, options.query ?? {}, options.body);
114
+ }
115
+ }
116
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { Query, Transport } from './transport.js';
2
+ export interface PageQuery {
3
+ cursor?: string;
4
+ limit?: number;
5
+ }
6
+ export interface Page<T> {
7
+ items: ReadonlyArray<T>;
8
+ nextCursor: string | null;
9
+ }
10
+ /** A list method as the auto-paginator sees it: give me a cursor, get a page. */
11
+ export type PageFetcher<T> = (cursor: string | undefined) => Promise<Page<T>>;
12
+ /**
13
+ * Walk every page of a cursor-paginated list.
14
+ *
15
+ * ```ts
16
+ * for await (const contact of chatly.contacts.listAll()) { … }
17
+ * ```
18
+ *
19
+ * Two safeguards, both earned. It stops when `nextCursor` is null — and also
20
+ * when the server hands back a cursor it already gave us, which would
21
+ * otherwise be an infinite loop issuing the same request forever. And it never
22
+ * paginates on `id`: ids in this product are a mix of UUID v4 and v7, so id
23
+ * order is not time order and keyset paging on it silently reorders results.
24
+ * Eighteen list endpoints were doing exactly that.
25
+ */
26
+ export declare function autoPaginate<T>(fetchPage: PageFetcher<T>): AsyncGenerator<T, void, void>;
27
+ /** Build a list namespace's two shapes — one page, and every page — from one path. */
28
+ export declare function listable<T>(transport: Transport, path: string, extra?: Query): {
29
+ list: (query?: PageQuery & Query) => Promise<Page<T>>;
30
+ listAll: (query?: Query) => AsyncGenerator<T, void, void>;
31
+ };
32
+ //# sourceMappingURL=pagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEvD,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,IAAI,CAAC,CAAC;IACrB,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,iFAAiF;AACjF,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9E;;;;;;;;;;;;;GAaG;AACH,wBAAuB,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAqB/F;AAED,sFAAsF;AACtF,wBAAgB,QAAQ,CAAC,CAAC,EACxB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,KAAU,GAChB;IACD,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;CAC3D,CAQA"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Walk every page of a cursor-paginated list.
3
+ *
4
+ * ```ts
5
+ * for await (const contact of chatly.contacts.listAll()) { … }
6
+ * ```
7
+ *
8
+ * Two safeguards, both earned. It stops when `nextCursor` is null — and also
9
+ * when the server hands back a cursor it already gave us, which would
10
+ * otherwise be an infinite loop issuing the same request forever. And it never
11
+ * paginates on `id`: ids in this product are a mix of UUID v4 and v7, so id
12
+ * order is not time order and keyset paging on it silently reorders results.
13
+ * Eighteen list endpoints were doing exactly that.
14
+ */
15
+ export async function* autoPaginate(fetchPage) {
16
+ const seen = new Set();
17
+ let cursor;
18
+ for (;;) {
19
+ const page = await fetchPage(cursor);
20
+ for (const item of page.items) {
21
+ yield item;
22
+ }
23
+ const next = page.nextCursor;
24
+ if (next === null || next === undefined || next === '') {
25
+ return;
26
+ }
27
+ if (seen.has(next)) {
28
+ throw new Error(`Chatly pagination stopped: the server repeated cursor "${next}". ` +
29
+ 'Continuing would issue the same request forever.');
30
+ }
31
+ seen.add(next);
32
+ cursor = next;
33
+ }
34
+ }
35
+ /** Build a list namespace's two shapes — one page, and every page — from one path. */
36
+ export function listable(transport, path, extra = {}) {
37
+ const list = (query = {}) => transport.get(path, { ...extra, ...query });
38
+ return {
39
+ list,
40
+ listAll: (query = {}) => autoPaginate((cursor) => list({ ...query, ...(cursor === undefined ? {} : { cursor }) })),
41
+ };
42
+ }
43
+ //# sourceMappingURL=pagination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,YAAY,CAAI,SAAyB;IAC9D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,MAA0B,CAAC;IAC/B,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,MAAM,IAAI,CAAC;QACb,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;QAC7B,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YACvD,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,0DAA0D,IAAI,KAAK;gBACjE,kDAAkD,CACrD,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,QAAQ,CACtB,SAAoB,EACpB,IAAY,EACZ,QAAe,EAAE;IAKjB,MAAM,IAAI,GAAG,CAAC,QAA2B,EAAE,EAAoB,EAAE,CAC/D,SAAS,CAAC,GAAG,CAAU,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IACvD,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,CAAC,QAAe,EAAE,EAAE,EAAE,CAC7B,YAAY,CAAI,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;KAC/F,CAAC;AACJ,CAAC"}
@@ -0,0 +1,237 @@
1
+ import { type Page, type PageQuery } from './pagination.js';
2
+ import type { Query, Transport } from './transport.js';
3
+ /**
4
+ * ── These shapes are READ OFF THE ZOD SCHEMAS, not guessed ───────────────
5
+ *
6
+ * The API validates every body with zod and zod DROPS unknown keys. A write
7
+ * with the wrong key name therefore returns 200 having done nothing, which no
8
+ * caller can distinguish from success. Three of this SDK's own writes were
9
+ * built that way until the Ruby SDK's author read the controllers:
10
+ *
11
+ * contacts.merge sent { sourceContactId } — schema wants { mergedId }
12
+ * contacts.addTags sent { tags: [...] } — schema wants { tag }, ONE
13
+ * contacts.unsubscribe sent { } — `unsubscribed` is REQUIRED
14
+ *
15
+ * The first two silently did nothing. The third 400'd, which is the lucky
16
+ * case. If you add a method here, open the schema.
17
+ */
18
+ export interface MergeContactInput {
19
+ /** The contact to merge INTO the target, and then retire. `contactMergeSchema`. */
20
+ mergedId: string;
21
+ }
22
+ export interface UnsubscribeContactInput {
23
+ /** Required. `false` re-subscribes. */
24
+ unsubscribed: boolean;
25
+ reason?: string;
26
+ }
27
+ export interface AgentHandlingInput {
28
+ /** `setAgentHandlingSchema` — the settable states, not the read states. */
29
+ state: string;
30
+ reason?: string | null;
31
+ }
32
+ export interface ScheduleMessageInput {
33
+ body: string;
34
+ /** ISO 8601 with offset. */
35
+ sendAt: string;
36
+ }
37
+ export interface ContactInput {
38
+ externalId?: string;
39
+ email?: string;
40
+ phone?: string;
41
+ name?: string;
42
+ attributes?: Record<string, unknown>;
43
+ }
44
+ export interface MessageInput {
45
+ conversationId: string;
46
+ body: string;
47
+ /**
48
+ * Mirrors `messageKindSchema`, all five members.
49
+ *
50
+ * `attachment_only` was missing here — the union listed four — so TypeScript
51
+ * refused the one kind you send when there are no words, only a file.
52
+ */
53
+ kind?: 'text' | 'rich' | 'note' | 'system_event' | 'attachment_only';
54
+ }
55
+ export interface MergeTicketsInput {
56
+ /**
57
+ * The ticket that LOSES — it is closed and its history moves to the one in
58
+ * the path. `{ loserId }`, not `{ sourceTicketId }`: a merge can only be
59
+ * read one way and the route is `:winnerId/merge`.
60
+ */
61
+ loserId: string;
62
+ }
63
+ export interface TrackEventInput {
64
+ contactId: string;
65
+ name: string;
66
+ properties?: Record<string, unknown>;
67
+ }
68
+ /** Query for `events.list` — a page, optionally one contact's. */
69
+ export interface EventListQuery extends PageQuery {
70
+ /** Restrict the stream to one contact. Omit for the whole workspace. */
71
+ contactId?: string;
72
+ }
73
+ /** A result shape we do not model field-by-field. The API validates; we pass through. */
74
+ export type Unmodelled = Record<string, unknown>;
75
+ export declare function contactsResource(t: Transport): {
76
+ get: (id: string) => Promise<Unmodelled>;
77
+ upsert: (body: ContactInput) => Promise<Unmodelled>;
78
+ /** Up to the API's documented batch ceiling per call. One idempotency key covers the batch. */
79
+ bulkUpsert: (contacts: ReadonlyArray<ContactInput>) => Promise<Unmodelled>;
80
+ merge: (id: string, body: MergeContactInput) => Promise<Unmodelled>;
81
+ /**
82
+ * Add ONE tag. The route's body is `{ tag }`, singular.
83
+ *
84
+ * Kept plural in the cross-language manifest (`contacts.add_tags`) because
85
+ * eight SDKs have locked that name, but the wire shape is one tag per
86
+ * call: loop for several. This sent `{ tags: [...] }`, which zod dropped,
87
+ * so it returned 200 and added nothing.
88
+ */
89
+ addTags: (id: string, tag: string) => Promise<Unmodelled>;
90
+ removeTag: (id: string, tag: string) => Promise<void>;
91
+ /**
92
+ * Opt the contact out of outbound email, or back in.
93
+ *
94
+ * `unsubscribed` is required — there is no default, and omitting it is a
95
+ * 400. Honoured across campaigns and workflows.
96
+ */
97
+ unsubscribe: (id: string, body: UnsubscribeContactInput) => Promise<Unmodelled>;
98
+ /** The contact's timeline: conversations, events, tickets, in one ordered read. */
99
+ journey: (id: string, query?: Query) => Promise<Unmodelled>;
100
+ list: (query?: PageQuery & Query) => Promise<Page<Unmodelled>>;
101
+ listAll: (query?: Query) => AsyncGenerator<Unmodelled, void, void>;
102
+ };
103
+ export declare function conversationsResource(t: Transport): {
104
+ get: (id: string) => Promise<Unmodelled>;
105
+ /**
106
+ * Read a thread before replying to it.
107
+ *
108
+ * The MCP server has exposed this as `get_messages` since it shipped and
109
+ * the SDK did not, so an integrator writing "read the conversation, then
110
+ * decide" against the SDK had to hand-roll the request while the same
111
+ * capability sat behind a tool call.
112
+ */
113
+ messages: (conversationId: string, query?: PageQuery & Query) => Promise<Page<Unmodelled>>;
114
+ send: (body: MessageInput) => Promise<Unmodelled>;
115
+ /** Open conversations with no agent reply yet — the queue a bot or a rota works from. */
116
+ unattended: (query?: Query) => Promise<Unmodelled>;
117
+ /** Is a human or a bot driving this thread right now. */
118
+ agentHandling: (id: string) => Promise<Unmodelled>;
119
+ /** Hand the thread to a bot, or take it back. `{ state, reason? }`. */
120
+ setAgentHandling: (id: string, body: AgentHandlingInput) => Promise<Unmodelled>;
121
+ /** Drafts the AI produced for this thread, newest first. */
122
+ generatedReplies: (id: string, query?: Query) => Promise<Unmodelled>;
123
+ /** Ask for a draft now. Returns the draft; it is not sent until you send it. */
124
+ generateReply: (id: string, body?: Unmodelled) => Promise<Unmodelled>;
125
+ scheduledMessages: (id: string, query?: Query) => Promise<Unmodelled>;
126
+ scheduleMessage: (id: string, body: ScheduleMessageInput) => Promise<Unmodelled>;
127
+ cancelScheduled: (scheduledId: string) => Promise<void>;
128
+ list: (query?: PageQuery & Query) => Promise<Page<Unmodelled>>;
129
+ listAll: (query?: Query) => AsyncGenerator<Unmodelled, void, void>;
130
+ };
131
+ export declare function ticketsResource(t: Transport): {
132
+ comments: (id: string, query?: Query) => Promise<Unmodelled>;
133
+ /** The ticket auto-created from a conversation, if there is one. */
134
+ forConversation: (conversationId: string) => Promise<Unmodelled>;
135
+ queues: () => Promise<Unmodelled>;
136
+ /** `id` is the WINNER; the body names the loser. */
137
+ merge: (id: string, body: MergeTicketsInput) => Promise<Unmodelled>;
138
+ split: (id: string, body: Unmodelled) => Promise<Unmodelled>;
139
+ /** One status, assignee or queue change applied to many tickets under one key. */
140
+ bulk: (body: Unmodelled) => Promise<Unmodelled>;
141
+ list: (query?: PageQuery & Query) => Promise<Page<Unmodelled>>;
142
+ listAll: (query?: Query) => AsyncGenerator<Unmodelled, void, void>;
143
+ };
144
+ export declare function macrosResource(t: Transport): {
145
+ create: (body: Unmodelled) => Promise<Unmodelled>;
146
+ update: (id: string, body: Unmodelled) => Promise<Unmodelled>;
147
+ delete: (id: string) => Promise<void>;
148
+ list: (query?: PageQuery & Query) => Promise<Page<Unmodelled>>;
149
+ listAll: (query?: Query) => AsyncGenerator<Unmodelled, void, void>;
150
+ };
151
+ export declare function kbResource(t: Transport): {
152
+ /** One article by slug — the same slug the help centre serves it under. */
153
+ article: (slug: string) => Promise<Unmodelled>;
154
+ collections: () => Promise<Unmodelled>;
155
+ list: (query?: PageQuery & Query) => Promise<Page<Unmodelled>>;
156
+ listAll: (query?: Query) => AsyncGenerator<Unmodelled, void, void>;
157
+ };
158
+ export declare function searchResource(t: Transport): {
159
+ /** Full-text across contacts, conversations, messages, tickets and the KB. */
160
+ query: (q: string, opts?: Query) => Promise<Unmodelled>;
161
+ /**
162
+ * Help-centre articles only.
163
+ *
164
+ * Sends `kinds=kb` as a repeated PLAIN key. It used to send `kinds[]=kb`,
165
+ * and `searchQuerySchema` is an object schema, so zod stripped the
166
+ * bracketed key and the search ran UNNARROWED — this method returned
167
+ * contacts, conversations, messages and tickets with a 200 and nothing to
168
+ * indicate the filter had been ignored. The MCP server's `search_kb` tool
169
+ * and the dashboard sent the same spelling. The schema now folds
170
+ * `kinds[]` and a scalar `kinds` as well, but the plain repeated key is
171
+ * the form to send.
172
+ */
173
+ kb: (q: string, opts?: Query) => Promise<Unmodelled>;
174
+ };
175
+ export declare function eventsResource(t: Transport): {
176
+ track: (input: TrackEventInput) => Promise<Unmodelled>;
177
+ /**
178
+ * Read back what was tracked — the same `/v1/cdp/events` collection
179
+ * `track` writes to, cursor-paginated newest-first.
180
+ *
181
+ * The SDK could write events and never read them, so "did my tracking
182
+ * call actually land?" had no answer outside the dashboard. Pass
183
+ * `contactId` to scope the stream to one person.
184
+ */
185
+ list: (query?: EventListQuery) => Promise<Page<Unmodelled>>;
186
+ listAll: (query?: Query) => AsyncGenerator<Unmodelled, void, void>;
187
+ };
188
+ export declare function webhooksResource(t: Transport): {
189
+ /** One delivery, with its request, response and attempt history. */
190
+ delivery: (id: string) => Promise<Unmodelled>;
191
+ /** Send it again. The receiver sees the same payload with a fresh signature. */
192
+ redeliver: (id: string) => Promise<Unmodelled>;
193
+ list: (query?: PageQuery & Query) => Promise<Page<Unmodelled>>;
194
+ listAll: (query?: Query) => AsyncGenerator<Unmodelled, void, void>;
195
+ };
196
+ export declare function reportsResource(t: Transport): {
197
+ overview: (query?: Query) => Promise<Unmodelled>;
198
+ agents: (query?: Query) => Promise<Unmodelled>;
199
+ conversationsByDay: (query?: Query) => Promise<Unmodelled>;
200
+ sla: (query?: Query) => Promise<Unmodelled>;
201
+ };
202
+ export declare function channelsResource(t: Transport): {
203
+ list: (query?: Query) => Promise<Unmodelled>;
204
+ get: (id: string) => Promise<Unmodelled>;
205
+ };
206
+ export declare function billingResource(t: Transport): {
207
+ /** The plan catalogue this deployment can actually sell. */
208
+ plans: () => Promise<Unmodelled>;
209
+ /** Current period usage, including AI spend against the workspace ceiling. */
210
+ usage: (query?: Query) => Promise<Unmodelled>;
211
+ };
212
+ export declare function workspaceResource(t: Transport): {
213
+ settings: () => Promise<Unmodelled>;
214
+ labels: () => Promise<Unmodelled>;
215
+ inboxes: () => Promise<Unmodelled>;
216
+ /**
217
+ * One team's roster. The only team read an API key can make.
218
+ *
219
+ * The workspace-wide `GET /v1/teams` list carries no `@AllowApiKey()` —
220
+ * it reads a calling user id, and a key is not a person — so it answers
221
+ * every key with 403. This manifest listed it anyway for a day, because
222
+ * the script that derived the key-accessible surface took the nearest
223
+ * `@AllowApiKey()` in either direction and credited the list route with
224
+ * the decorator belonging to this one. Get a team id from a workflow, an
225
+ * inbox's `settings.routingTeamId`, or a conversation's `teamId`.
226
+ */
227
+ teamMembers: (teamId: string) => Promise<Unmodelled>;
228
+ /**
229
+ * The workspace's skill taxonomy — the distinct labels routing matches on.
230
+ *
231
+ * `GET /v1/agents` has no handler at all; the agents controller serves
232
+ * only `/agents/skills` and `/agents/{userId}/skills`. There is no
233
+ * key-accessible way to list the people with a seat here.
234
+ */
235
+ agentSkills: () => Promise<Unmodelled>;
236
+ };
237
+ //# sourceMappingURL=resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}