@curviate/sdk 0.18.0 → 0.19.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/CHANGELOG.md +73 -0
- package/README.md +29 -16
- package/dist/index.d.ts +80 -45
- package/dist/index.js +25 -15
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,79 @@ Versioning: semantic — minor for additive changes, patch for bug fixes; no sta
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.19.0] - 2026-08-03
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **`constructEvent` now parses real webhook deliveries. It previously rejected
|
|
17
|
+
every single one.** The Curviate platform sends the event name in `event`;
|
|
18
|
+
the SDK required a `type` field that no delivery has ever contained, so
|
|
19
|
+
verification threw `WebhookSignatureError` on 100% of genuine webhooks. The
|
|
20
|
+
HMAC path was never at fault (a tampered body was correctly rejected as
|
|
21
|
+
`invalid_signature`); the parse step was. If webhook verification has never
|
|
22
|
+
worked for you, this is why, and this release fixes it.
|
|
23
|
+
|
|
24
|
+
- **A body problem no longer reports a header problem.** A payload whose
|
|
25
|
+
signature verifies but whose body cannot be parsed used to fail with
|
|
26
|
+
`reason: "malformed_header"`, pointing at the two things that had just been
|
|
27
|
+
proven correct: the header and the signing secret. Integrators read that and
|
|
28
|
+
rotated a secret that was never wrong. Those cases now report the new
|
|
29
|
+
`reason: "malformed_payload"`, and the message no longer mentions the header,
|
|
30
|
+
the signature, or the secret.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- **BREAKING (type-level), and it breaks no working code.** The `CurviateEvent`
|
|
35
|
+
discriminant is now `event`, not `type`:
|
|
36
|
+
|
|
37
|
+
```diff
|
|
38
|
+
- if (event.type === "message.received") { ... }
|
|
39
|
+
+ if (event.event === "message.received") { ... }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Read the label carefully before deferring the upgrade: **there is no working
|
|
43
|
+
consumer of `event.type` to break.** `constructEvent` has never once returned
|
|
44
|
+
successfully for a real delivery, so no `event.type` branch has ever executed
|
|
45
|
+
in production. Any handler you have written behind it is unreachable code
|
|
46
|
+
today. `event.type` is now a compile error precisely so `tsc` points you at
|
|
47
|
+
every site that needs the one-word edit; nothing changes at runtime for code
|
|
48
|
+
that was previously working, because there was none.
|
|
49
|
+
|
|
50
|
+
`WebhookSignatureError["reason"]` gains the `"malformed_payload"` member. An
|
|
51
|
+
exhaustive `switch` over `reason` will need the new arm.
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- **`CurviateEventEnvelope`**: the per-delivery metadata now carried on every
|
|
56
|
+
event. `event.id` is the `wdl_…` delivery id (de-duplicate retries on it),
|
|
57
|
+
`event.webhook_id` is the registration, `event.delivered_at` is the attempt
|
|
58
|
+
timestamp. These are typed optional and are **not** required by the parser:
|
|
59
|
+
requiring an envelope field is what caused this defect, so nothing beyond the
|
|
60
|
+
discriminant can fail a verification again.
|
|
61
|
+
|
|
62
|
+
- Forward compatibility: a payload carrying `type` instead of `event` is
|
|
63
|
+
accepted and normalized onto `event`, so a future platform-side change to the
|
|
64
|
+
envelope cannot break verification a second time. `type` is never required.
|
|
65
|
+
|
|
66
|
+
- `test/webhooks.dispatcherEnvelope.test.ts` and
|
|
67
|
+
`test/fixtures/webhook-delivery.capture.json`: the regression test replays
|
|
68
|
+
bytes and a signature header **captured off the wire from the real dispatch
|
|
69
|
+
worker**, rather than constructing its own payload. The pre-existing suite was
|
|
70
|
+
green throughout this defect because it built its own `{ type: … }` fixtures;
|
|
71
|
+
a suite that constructs its own input cannot detect an emitter/parser
|
|
72
|
+
divergence, and that is what let this ship.
|
|
73
|
+
|
|
74
|
+
## [0.18.1] — 2026-07-18
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
|
|
78
|
+
- **`companies.sendMessage(identifier, chatId, body)`** now takes the normal `2-…`
|
|
79
|
+
chat id that `companies.chats()` / `chat()` / `searchChats()` return; the endpoint
|
|
80
|
+
resolves the page mailbox internally from `identifier`. The previous send-ready
|
|
81
|
+
`COMPANY_` chat-id requirement is gone: pass the id straight from the company chat
|
|
82
|
+
reads. Method signature and response shape are unchanged (documentation/behavior
|
|
83
|
+
only).
|
|
84
|
+
|
|
12
85
|
## [0.18.0] — 2026-07-17
|
|
13
86
|
|
|
14
87
|
### Added
|
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# @curviate/sdk
|
|
2
2
|
|
|
3
|
-
The official TypeScript SDK for the [Curviate API](https://docs.curviate.com)
|
|
3
|
+
The official TypeScript SDK for the [Curviate API](https://docs.curviate.com). Agent-native
|
|
4
4
|
LinkedIn infrastructure for AI engineers and agent builders.
|
|
5
5
|
|
|
6
|
-
> **Status:**
|
|
6
|
+
> **Status:** pre-1.0. Full v2 API parity; the surface is public but not yet stability-promised.
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -17,7 +17,7 @@ Requires Node 18+. Works in Cloudflare Workers and Vercel Edge.
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
## Auth
|
|
20
|
+
## Auth: construct the client
|
|
21
21
|
|
|
22
22
|
Get your API key from the Curviate dashboard. Store it as an environment variable.
|
|
23
23
|
|
|
@@ -37,7 +37,7 @@ const curviate = new Curviate({
|
|
|
37
37
|
|
|
38
38
|
## Account-scoped accessor
|
|
39
39
|
|
|
40
|
-
Every LinkedIn operation (messages, member profiles, invites, posts) is tied to a **managed account
|
|
40
|
+
Every LinkedIn operation (messages, member profiles, invites, posts) is tied to a **managed account**, a LinkedIn session you have connected via the connect flow (`curviate.auth.intent()`). The `curviate.account(id)` accessor fixes the `account_id` on every call so you do not have to thread it manually:
|
|
41
41
|
|
|
42
42
|
```ts
|
|
43
43
|
// Root-level: tenant-wide operations (accounts, auth, webhooks)
|
|
@@ -56,7 +56,7 @@ const profile = await acc.users.get("some-user-id"); // someone else's
|
|
|
56
56
|
|
|
57
57
|
## First end-to-end call
|
|
58
58
|
|
|
59
|
-
This snippet lists your connected accounts, picks the first one, and sends a message
|
|
59
|
+
This snippet lists your connected accounts, picks the first one, and sends a message, something an agent might do to automate outreach:
|
|
60
60
|
|
|
61
61
|
```ts
|
|
62
62
|
import { Curviate, isCurviateError } from "@curviate/sdk";
|
|
@@ -78,7 +78,7 @@ async function sendFirstMessage() {
|
|
|
78
78
|
// 3. Send a message to the first chat
|
|
79
79
|
const chat = chats[0]!;
|
|
80
80
|
await acc.messaging.sendMessage(chat.id ?? "", {
|
|
81
|
-
text: "Hi
|
|
81
|
+
text: "Hi, following up from our conversation.",
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
console.log("Message sent.");
|
|
@@ -114,7 +114,7 @@ try {
|
|
|
114
114
|
break;
|
|
115
115
|
default:
|
|
116
116
|
if (err.retryLikelyToSucceed) {
|
|
117
|
-
// Safe to retry
|
|
117
|
+
// Safe to retry: server-side transient error
|
|
118
118
|
await retry();
|
|
119
119
|
}
|
|
120
120
|
}
|
|
@@ -127,7 +127,7 @@ All 34 error codes are documented in the [API reference](https://docs.curviate.c
|
|
|
127
127
|
|
|
128
128
|
## Cursor pagination
|
|
129
129
|
|
|
130
|
-
Resources that return lists support cursor pagination. `curviate.paginate()` is an async iterator that follows the `cursor` field automatically
|
|
130
|
+
Resources that return lists support cursor pagination. `curviate.paginate()` is an async iterator that follows the `cursor` field automatically, so you pull items one at a time without managing cursors:
|
|
131
131
|
|
|
132
132
|
```ts
|
|
133
133
|
// Iterate over every chat across all pages
|
|
@@ -163,27 +163,28 @@ app.post("/webhook", express.raw({ type: "application/json" }), async (req, res)
|
|
|
163
163
|
event = await constructEvent(req.body, sig, secret);
|
|
164
164
|
} catch (err) {
|
|
165
165
|
if (err instanceof WebhookSignatureError) {
|
|
166
|
-
|
|
166
|
+
// 'invalid_signature' | 'replay_detected' | 'malformed_header' | 'malformed_payload'
|
|
167
|
+
console.warn("Bad webhook:", err.reason);
|
|
167
168
|
return res.sendStatus(400);
|
|
168
169
|
}
|
|
169
170
|
throw err;
|
|
170
171
|
}
|
|
171
172
|
|
|
172
|
-
switch (event.
|
|
173
|
+
switch (event.event) {
|
|
173
174
|
case "message.received":
|
|
174
|
-
// event.data is MessagePayload
|
|
175
|
+
// event.data is MessagePayload: account_id, message_id, and so on.
|
|
175
176
|
handleNewMessage(event.data);
|
|
176
177
|
break;
|
|
177
178
|
case "account.connected":
|
|
178
179
|
handleAccountConnected(event.data);
|
|
179
180
|
break;
|
|
180
|
-
// 22 more event types
|
|
181
|
+
// 22 more event types, all in the CurviateEvent union.
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
res.sendStatus(200);
|
|
184
185
|
});
|
|
185
186
|
|
|
186
|
-
// Hono / Vercel Edge
|
|
187
|
+
// Hono / Vercel Edge. Always await; Web Crypto is async.
|
|
187
188
|
app.post("/webhook", async (c) => {
|
|
188
189
|
const rawBody = await c.req.text();
|
|
189
190
|
const event = await constructEvent(rawBody, c.req.header("curviate-signature")!, secret);
|
|
@@ -191,16 +192,28 @@ app.post("/webhook", async (c) => {
|
|
|
191
192
|
});
|
|
192
193
|
```
|
|
193
194
|
|
|
194
|
-
`constructEvent` always returns a `Promise<CurviateEvent
|
|
195
|
+
`constructEvent` always returns a `Promise<CurviateEvent>`. Always `await` it.
|
|
195
196
|
|
|
196
|
-
|
|
197
|
+
Each event also carries its delivery metadata: `event.id` (a `wdl_` delivery id you
|
|
198
|
+
can de-duplicate retries on), `event.webhook_id`, and `event.delivered_at`.
|
|
199
|
+
|
|
200
|
+
`WebhookSignatureError` is NOT a `CurviateError`. Narrow with `instanceof WebhookSignatureError`.
|
|
201
|
+
Its `reason` tells you where to look: `malformed_header` means the signature header could not be
|
|
202
|
+
read, `invalid_signature` means the HMAC did not match (check the secret, and check that you passed
|
|
203
|
+
the raw request bytes), `replay_detected` means the event is outside the replay window, and
|
|
204
|
+
`malformed_payload` means the signature was **valid** but the body was not a Curviate event, so
|
|
205
|
+
your secret and header are both fine.
|
|
206
|
+
|
|
207
|
+
> **Upgrading from 0.18.x or earlier?** The event discriminant is `event.event`, not `event.type`.
|
|
208
|
+
> See the 0.19.0 entry in [CHANGELOG.md](./CHANGELOG.md); the change is a one-word edit and it
|
|
209
|
+
> breaks no working code, because `constructEvent` never returned successfully before 0.19.0.
|
|
197
210
|
|
|
198
211
|
---
|
|
199
212
|
|
|
200
213
|
## Links
|
|
201
214
|
|
|
202
215
|
- API reference: https://docs.curviate.com
|
|
203
|
-
- Issues: https://github.com/curviate/sdk/issues
|
|
216
|
+
- Issues: https://github.com/curviate/curviate-sdk/issues
|
|
204
217
|
- Changelog: [CHANGELOG.md](./CHANGELOG.md)
|
|
205
218
|
|
|
206
219
|
## License
|
package/dist/index.d.ts
CHANGED
|
@@ -28709,9 +28709,10 @@ declare class JobsResource {
|
|
|
28709
28709
|
* busier inbox.
|
|
28710
28710
|
*
|
|
28711
28711
|
* `sendMessage()` is the inbox's one write: reply to an existing
|
|
28712
|
-
* conversation AS THE PAGE. It
|
|
28713
|
-
*
|
|
28714
|
-
* Reply-only, same admin
|
|
28712
|
+
* conversation AS THE PAGE. It takes the same `2-…` chat id that
|
|
28713
|
+
* `chats()` / `searchChats()` return; the endpoint resolves the page
|
|
28714
|
+
* mailbox internally from `identifier`. Reply-only, same admin
|
|
28715
|
+
* requirement as the reads.
|
|
28715
28716
|
*/
|
|
28716
28717
|
|
|
28717
28718
|
type CompanyProfile = paths["/v1/{account_id}/companies/{identifier}"]["get"]["responses"]["200"]["content"]["application/json"];
|
|
@@ -28866,11 +28867,10 @@ declare class CompaniesResource {
|
|
|
28866
28867
|
* Reply to a company-inbox conversation, AS THE PAGE.
|
|
28867
28868
|
* `POST /v1/{account_id}/companies/{identifier}/chats/{chat_id}/messages`
|
|
28868
28869
|
*
|
|
28869
|
-
* `chatId`
|
|
28870
|
-
* `
|
|
28871
|
-
*
|
|
28872
|
-
*
|
|
28873
|
-
* the required form and its source.
|
|
28870
|
+
* `chatId` is the `2-…` conversation id that `chats()` / `chat()` /
|
|
28871
|
+
* `searchChats()` return for this page. The endpoint resolves the page
|
|
28872
|
+
* mailbox internally from `identifier`, so no special send-ready id is
|
|
28873
|
+
* needed: pass the id straight from the company chat reads.
|
|
28874
28874
|
*
|
|
28875
28875
|
* Reply-only: this method can only answer an existing conversation, it
|
|
28876
28876
|
* cannot start a new one on the page's behalf. The connected account
|
|
@@ -28886,13 +28886,9 @@ declare class CompaniesResource {
|
|
|
28886
28886
|
*
|
|
28887
28887
|
* @example
|
|
28888
28888
|
* const acc = curviate.account("acc_YOUR_ACCOUNT_ID");
|
|
28889
|
-
* const { items:
|
|
28890
|
-
* const pageInbox = inboxes[0]!; // e.g. id "COMPANY_83734124_PRIMARY"
|
|
28891
|
-
*
|
|
28892
|
-
* const { items: chats } = await acc.inboxes.listChats(pageInbox.id);
|
|
28893
|
-
* const chatId = chats[0]!.id as string; // e.g. "COMPANY_83734124_2-YTQ3ODU3Njgt"
|
|
28889
|
+
* const { items: chats } = await acc.companies.chats("112013061");
|
|
28894
28890
|
*
|
|
28895
|
-
* const result = await acc.companies.sendMessage("112013061",
|
|
28891
|
+
* const result = await acc.companies.sendMessage("112013061", chats[0]!.id, {
|
|
28896
28892
|
* text: "Thanks for reaching out, happy to help!",
|
|
28897
28893
|
* });
|
|
28898
28894
|
* console.log(result.sent_as); // { kind: "company", company_id: "112013061", name: "RedHire" }
|
|
@@ -29215,6 +29211,20 @@ declare function isCurviateError(err: unknown): err is CurviateError;
|
|
|
29215
29211
|
* Extends `Error`, NOT `CurviateError` — callers can narrow with
|
|
29216
29212
|
* `instanceof WebhookSignatureError` independently of CurviateError.
|
|
29217
29213
|
*
|
|
29214
|
+
* The `reason` codes split by where the problem actually is, so the code you
|
|
29215
|
+
* read points at the thing you need to look at:
|
|
29216
|
+
*
|
|
29217
|
+
* - `malformed_header` - the `Curviate-Signature` header itself is unusable
|
|
29218
|
+
* (missing `t=` or `v1=`, non-numeric timestamp). Check how you are reading
|
|
29219
|
+
* the header.
|
|
29220
|
+
* - `invalid_signature` - the header parsed, but the HMAC does not match.
|
|
29221
|
+
* Check the signing secret, and check that you passed the raw request bytes
|
|
29222
|
+
* rather than a re-serialized object.
|
|
29223
|
+
* - `replay_detected` - signature valid, timestamp outside the replay window.
|
|
29224
|
+
* - `malformed_payload` - **signature valid**, but the body is not a Curviate
|
|
29225
|
+
* event. Nothing is wrong with your secret or your header; look at what is
|
|
29226
|
+
* POSTing to the endpoint.
|
|
29227
|
+
*
|
|
29218
29228
|
* @example
|
|
29219
29229
|
* try {
|
|
29220
29230
|
* const event = await constructEvent(rawBody, header, secret);
|
|
@@ -29227,7 +29237,7 @@ declare function isCurviateError(err: unknown): err is CurviateError;
|
|
|
29227
29237
|
declare class WebhookSignatureError extends Error {
|
|
29228
29238
|
readonly name = "WebhookSignatureError";
|
|
29229
29239
|
/** Structured reason code for the verification failure. */
|
|
29230
|
-
readonly reason: "invalid_signature" | "replay_detected" | "malformed_header";
|
|
29240
|
+
readonly reason: "invalid_signature" | "replay_detected" | "malformed_header" | "malformed_payload";
|
|
29231
29241
|
constructor(reason: WebhookSignatureError["reason"], message: string);
|
|
29232
29242
|
}
|
|
29233
29243
|
/**
|
|
@@ -29252,9 +29262,34 @@ interface AccountPayload {
|
|
|
29252
29262
|
account_id: string;
|
|
29253
29263
|
[key: string]: unknown;
|
|
29254
29264
|
}
|
|
29265
|
+
/**
|
|
29266
|
+
* Delivery metadata that accompanies every Curviate webhook event.
|
|
29267
|
+
*
|
|
29268
|
+
* These fields are present on every delivery the platform sends, but
|
|
29269
|
+
* `constructEvent` does **not** require them: the parser insists only on the
|
|
29270
|
+
* discriminant. That is deliberate. Requiring an envelope field is exactly how
|
|
29271
|
+
* verification broke before (the parser demanded a field the emitter did not
|
|
29272
|
+
* send, and rejected every genuine delivery), so anything the union does not
|
|
29273
|
+
* strictly need to narrow is optional here and cannot fail a verification.
|
|
29274
|
+
*/
|
|
29275
|
+
interface CurviateEventEnvelope {
|
|
29276
|
+
/** Unique id for this delivery attempt, e.g. `wdl_01J...`. Use it to de-duplicate retries. */
|
|
29277
|
+
id?: string;
|
|
29278
|
+
/** Id of the webhook registration this delivery belongs to, e.g. `wh_01J...`. */
|
|
29279
|
+
webhook_id?: string;
|
|
29280
|
+
/** ISO-8601 timestamp of the delivery attempt. */
|
|
29281
|
+
delivered_at?: string;
|
|
29282
|
+
}
|
|
29255
29283
|
/**
|
|
29256
29284
|
* The complete discriminated union of all 24 canonical, create-subscribable
|
|
29257
|
-
* Curviate webhook events. The
|
|
29285
|
+
* Curviate webhook events. The **`event`** field is the discriminant, matching
|
|
29286
|
+
* the field the platform actually sends on the wire.
|
|
29287
|
+
*
|
|
29288
|
+
* > Migrating from 0.18.x and earlier: the discriminant was `type`, a field no
|
|
29289
|
+
* > Curviate delivery has ever contained, so `constructEvent` threw on every
|
|
29290
|
+
* > real webhook and no `event.type` branch could ever run. Switch your checks
|
|
29291
|
+
* > to `event.event === '...'`. `event.type` is now a compile error, which is
|
|
29292
|
+
* > intentional: it points at every site that needs the one-word change.
|
|
29258
29293
|
*
|
|
29259
29294
|
* Re-keyed for the v2 catalogue (was 19). Renamed/removed vs. the prior set:
|
|
29260
29295
|
* `account.stopped`, `account.sync_started`, `account.sync_complete`,
|
|
@@ -29269,83 +29304,83 @@ interface AccountPayload {
|
|
|
29269
29304
|
*
|
|
29270
29305
|
* @example
|
|
29271
29306
|
* const event = await constructEvent(rawBody, header, secret);
|
|
29272
|
-
* if (event.
|
|
29307
|
+
* if (event.event === 'message.received') {
|
|
29273
29308
|
* // event.data is MessagePayload
|
|
29274
29309
|
* }
|
|
29275
29310
|
*/
|
|
29276
|
-
type CurviateEvent = {
|
|
29277
|
-
|
|
29311
|
+
type CurviateEvent = CurviateEventEnvelope & ({
|
|
29312
|
+
event: "message.received";
|
|
29278
29313
|
data: MessagePayload;
|
|
29279
29314
|
} | {
|
|
29280
|
-
|
|
29315
|
+
event: "message.delivered";
|
|
29281
29316
|
data: MessagePayload;
|
|
29282
29317
|
} | {
|
|
29283
|
-
|
|
29318
|
+
event: "message.read";
|
|
29284
29319
|
data: MessagePayload;
|
|
29285
29320
|
} | {
|
|
29286
|
-
|
|
29321
|
+
event: "message.edited";
|
|
29287
29322
|
data: MessagePayload;
|
|
29288
29323
|
} | {
|
|
29289
|
-
|
|
29324
|
+
event: "message.deleted";
|
|
29290
29325
|
data: MessagePayload;
|
|
29291
29326
|
} | {
|
|
29292
|
-
|
|
29327
|
+
event: "message.reaction";
|
|
29293
29328
|
data: MessagePayload;
|
|
29294
29329
|
} | {
|
|
29295
|
-
|
|
29330
|
+
event: "chat.updated";
|
|
29296
29331
|
data: MessagePayload;
|
|
29297
29332
|
} | {
|
|
29298
|
-
|
|
29333
|
+
event: "chat.deleted";
|
|
29299
29334
|
data: MessagePayload;
|
|
29300
29335
|
} | {
|
|
29301
|
-
|
|
29336
|
+
event: "connection.accepted";
|
|
29302
29337
|
data: ConnectionPayload;
|
|
29303
29338
|
} | {
|
|
29304
|
-
|
|
29339
|
+
event: "connection.new";
|
|
29305
29340
|
data: ConnectionPayload;
|
|
29306
29341
|
} | {
|
|
29307
|
-
|
|
29342
|
+
event: "account.created";
|
|
29308
29343
|
data: AccountPayload;
|
|
29309
29344
|
} | {
|
|
29310
|
-
|
|
29345
|
+
event: "account.connected";
|
|
29311
29346
|
data: AccountPayload;
|
|
29312
29347
|
} | {
|
|
29313
|
-
|
|
29348
|
+
event: "account.synced";
|
|
29314
29349
|
data: AccountPayload;
|
|
29315
29350
|
} | {
|
|
29316
|
-
|
|
29351
|
+
event: "account.reconnected";
|
|
29317
29352
|
data: AccountPayload;
|
|
29318
29353
|
} | {
|
|
29319
|
-
|
|
29354
|
+
event: "account.reconnect_needed";
|
|
29320
29355
|
data: AccountPayload;
|
|
29321
29356
|
} | {
|
|
29322
|
-
|
|
29357
|
+
event: "account.creation_failed";
|
|
29323
29358
|
data: AccountPayload;
|
|
29324
29359
|
} | {
|
|
29325
|
-
|
|
29360
|
+
event: "account.disconnected";
|
|
29326
29361
|
data: AccountPayload;
|
|
29327
29362
|
} | {
|
|
29328
|
-
|
|
29363
|
+
event: "account.error";
|
|
29329
29364
|
data: AccountPayload;
|
|
29330
29365
|
} | {
|
|
29331
|
-
|
|
29366
|
+
event: "account.paused";
|
|
29332
29367
|
data: AccountPayload;
|
|
29333
29368
|
} | {
|
|
29334
|
-
|
|
29369
|
+
event: "account.connecting";
|
|
29335
29370
|
data: AccountPayload;
|
|
29336
29371
|
} | {
|
|
29337
|
-
|
|
29372
|
+
event: "account.permission_revoked";
|
|
29338
29373
|
data: AccountPayload;
|
|
29339
29374
|
} | {
|
|
29340
|
-
|
|
29375
|
+
event: "account.initial_sync.running";
|
|
29341
29376
|
data: AccountPayload;
|
|
29342
29377
|
} | {
|
|
29343
|
-
|
|
29378
|
+
event: "account.initial_sync.completed";
|
|
29344
29379
|
data: AccountPayload;
|
|
29345
29380
|
} | {
|
|
29346
|
-
|
|
29381
|
+
event: "account.initial_sync.failed";
|
|
29347
29382
|
data: AccountPayload;
|
|
29348
|
-
};
|
|
29383
|
+
});
|
|
29349
29384
|
/**
|
|
29350
29385
|
* Options for {@link constructEvent}.
|
|
29351
29386
|
*/
|
|
@@ -29390,7 +29425,7 @@ interface ConstructEventOptions {
|
|
|
29390
29425
|
* }
|
|
29391
29426
|
* throw err;
|
|
29392
29427
|
* }
|
|
29393
|
-
* if (event.
|
|
29428
|
+
* if (event.event === 'message.received') { ... }
|
|
29394
29429
|
* res.sendStatus(200);
|
|
29395
29430
|
* });
|
|
29396
29431
|
*
|
|
@@ -29404,4 +29439,4 @@ interface ConstructEventOptions {
|
|
|
29404
29439
|
*/
|
|
29405
29440
|
declare function constructEvent(rawBody: string | Buffer, signatureHeader: string, secret: string, opts?: ConstructEventOptions): Promise<CurviateEvent>;
|
|
29406
29441
|
|
|
29407
|
-
export { type AccountListPage, type AccountListParams, type AccountPayload, type AccountScopedNamespaces, type ConnectionPayload, type ConstructEventOptions, Curviate, type CurviateConfig, CurviateError, type CurviateErrorInit, type CurviateErrorJSON, type CurviateEvent, type ErrorCode, type MessagePayload, type RequiredTier, type ResolvedConfig, type ResourceNamespaces, type RetryHint, WebhookSignatureError, type components, constructEvent, isCurviateError, type operations, type paths };
|
|
29442
|
+
export { type AccountListPage, type AccountListParams, type AccountPayload, type AccountScopedNamespaces, type ConnectionPayload, type ConstructEventOptions, Curviate, type CurviateConfig, CurviateError, type CurviateErrorInit, type CurviateErrorJSON, type CurviateEvent, type CurviateEventEnvelope, type ErrorCode, type MessagePayload, type RequiredTier, type ResolvedConfig, type ResourceNamespaces, type RetryHint, WebhookSignatureError, type components, constructEvent, isCurviateError, type operations, type paths };
|
package/dist/index.js
CHANGED
|
@@ -2375,11 +2375,10 @@ var CompaniesResource = class {
|
|
|
2375
2375
|
* Reply to a company-inbox conversation, AS THE PAGE.
|
|
2376
2376
|
* `POST /v1/{account_id}/companies/{identifier}/chats/{chat_id}/messages`
|
|
2377
2377
|
*
|
|
2378
|
-
* `chatId`
|
|
2379
|
-
* `
|
|
2380
|
-
*
|
|
2381
|
-
*
|
|
2382
|
-
* the required form and its source.
|
|
2378
|
+
* `chatId` is the `2-…` conversation id that `chats()` / `chat()` /
|
|
2379
|
+
* `searchChats()` return for this page. The endpoint resolves the page
|
|
2380
|
+
* mailbox internally from `identifier`, so no special send-ready id is
|
|
2381
|
+
* needed: pass the id straight from the company chat reads.
|
|
2383
2382
|
*
|
|
2384
2383
|
* Reply-only: this method can only answer an existing conversation, it
|
|
2385
2384
|
* cannot start a new one on the page's behalf. The connected account
|
|
@@ -2395,13 +2394,9 @@ var CompaniesResource = class {
|
|
|
2395
2394
|
*
|
|
2396
2395
|
* @example
|
|
2397
2396
|
* const acc = curviate.account("acc_YOUR_ACCOUNT_ID");
|
|
2398
|
-
* const { items:
|
|
2399
|
-
* const pageInbox = inboxes[0]!; // e.g. id "COMPANY_83734124_PRIMARY"
|
|
2400
|
-
*
|
|
2401
|
-
* const { items: chats } = await acc.inboxes.listChats(pageInbox.id);
|
|
2402
|
-
* const chatId = chats[0]!.id as string; // e.g. "COMPANY_83734124_2-YTQ3ODU3Njgt"
|
|
2397
|
+
* const { items: chats } = await acc.companies.chats("112013061");
|
|
2403
2398
|
*
|
|
2404
|
-
* const result = await acc.companies.sendMessage("112013061",
|
|
2399
|
+
* const result = await acc.companies.sendMessage("112013061", chats[0]!.id, {
|
|
2405
2400
|
* text: "Thanks for reaching out, happy to help!",
|
|
2406
2401
|
* });
|
|
2407
2402
|
* console.log(result.sent_as); // { kind: "company", company_id: "112013061", name: "RedHire" }
|
|
@@ -2689,12 +2684,27 @@ function verifyAndParse(computedHex, v1, timestamp, bodyStr, replayWindowSecs) {
|
|
|
2689
2684
|
try {
|
|
2690
2685
|
parsed = JSON.parse(bodyStr);
|
|
2691
2686
|
} catch {
|
|
2692
|
-
throw new WebhookSignatureError(
|
|
2687
|
+
throw new WebhookSignatureError(
|
|
2688
|
+
"malformed_payload",
|
|
2689
|
+
"Webhook body is not valid JSON. Verification already succeeded, so the problem is the request body, not your webhook configuration."
|
|
2690
|
+
);
|
|
2693
2691
|
}
|
|
2694
|
-
if (typeof parsed !== "object" || parsed === null ||
|
|
2695
|
-
throw new WebhookSignatureError(
|
|
2692
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2693
|
+
throw new WebhookSignatureError(
|
|
2694
|
+
"malformed_payload",
|
|
2695
|
+
"Webhook body is not a JSON object. Verification already succeeded, so the problem is the request body, not your webhook configuration."
|
|
2696
|
+
);
|
|
2697
|
+
}
|
|
2698
|
+
const record = parsed;
|
|
2699
|
+
const discriminant = typeof record["event"] === "string" ? record["event"] : typeof record["type"] === "string" ? record["type"] : void 0;
|
|
2700
|
+
if (discriminant === void 0) {
|
|
2701
|
+
throw new WebhookSignatureError(
|
|
2702
|
+
"malformed_payload",
|
|
2703
|
+
'Webhook body has no "event" field, so it cannot be resolved to a Curviate event. Verification already succeeded, so the problem is the request body, not your webhook configuration.'
|
|
2704
|
+
);
|
|
2696
2705
|
}
|
|
2697
|
-
|
|
2706
|
+
record["event"] = discriminant;
|
|
2707
|
+
return record;
|
|
2698
2708
|
}
|
|
2699
2709
|
async function constructEvent(rawBody, signatureHeader, secret, opts) {
|
|
2700
2710
|
const replayWindowSecs = opts?.replayWindowSecs ?? 300;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@curviate/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "TypeScript SDK for the Curviate API.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
"homepage": "https://docs.curviate.com",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/curviate/sdk.git"
|
|
11
|
+
"url": "git+https://github.com/curviate/curviate-sdk.git"
|
|
12
12
|
},
|
|
13
13
|
"bugs": {
|
|
14
|
-
"url": "https://github.com/curviate/sdk/issues"
|
|
14
|
+
"url": "https://github.com/curviate/curviate-sdk/issues"
|
|
15
15
|
},
|
|
16
16
|
"publishConfig": {
|
|
17
17
|
"access": "public"
|