@curviate/sdk 0.18.1 → 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 +62 -0
- package/README.md +29 -16
- package/dist/index.d.ts +70 -31
- package/dist/index.js +19 -4
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,68 @@ 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
|
+
|
|
12
74
|
## [0.18.1] — 2026-07-18
|
|
13
75
|
|
|
14
76
|
### Changed
|
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
|
@@ -29211,6 +29211,20 @@ declare function isCurviateError(err: unknown): err is CurviateError;
|
|
|
29211
29211
|
* Extends `Error`, NOT `CurviateError` — callers can narrow with
|
|
29212
29212
|
* `instanceof WebhookSignatureError` independently of CurviateError.
|
|
29213
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
|
+
*
|
|
29214
29228
|
* @example
|
|
29215
29229
|
* try {
|
|
29216
29230
|
* const event = await constructEvent(rawBody, header, secret);
|
|
@@ -29223,7 +29237,7 @@ declare function isCurviateError(err: unknown): err is CurviateError;
|
|
|
29223
29237
|
declare class WebhookSignatureError extends Error {
|
|
29224
29238
|
readonly name = "WebhookSignatureError";
|
|
29225
29239
|
/** Structured reason code for the verification failure. */
|
|
29226
|
-
readonly reason: "invalid_signature" | "replay_detected" | "malformed_header";
|
|
29240
|
+
readonly reason: "invalid_signature" | "replay_detected" | "malformed_header" | "malformed_payload";
|
|
29227
29241
|
constructor(reason: WebhookSignatureError["reason"], message: string);
|
|
29228
29242
|
}
|
|
29229
29243
|
/**
|
|
@@ -29248,9 +29262,34 @@ interface AccountPayload {
|
|
|
29248
29262
|
account_id: string;
|
|
29249
29263
|
[key: string]: unknown;
|
|
29250
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
|
+
}
|
|
29251
29283
|
/**
|
|
29252
29284
|
* The complete discriminated union of all 24 canonical, create-subscribable
|
|
29253
|
-
* 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.
|
|
29254
29293
|
*
|
|
29255
29294
|
* Re-keyed for the v2 catalogue (was 19). Renamed/removed vs. the prior set:
|
|
29256
29295
|
* `account.stopped`, `account.sync_started`, `account.sync_complete`,
|
|
@@ -29265,83 +29304,83 @@ interface AccountPayload {
|
|
|
29265
29304
|
*
|
|
29266
29305
|
* @example
|
|
29267
29306
|
* const event = await constructEvent(rawBody, header, secret);
|
|
29268
|
-
* if (event.
|
|
29307
|
+
* if (event.event === 'message.received') {
|
|
29269
29308
|
* // event.data is MessagePayload
|
|
29270
29309
|
* }
|
|
29271
29310
|
*/
|
|
29272
|
-
type CurviateEvent = {
|
|
29273
|
-
|
|
29311
|
+
type CurviateEvent = CurviateEventEnvelope & ({
|
|
29312
|
+
event: "message.received";
|
|
29274
29313
|
data: MessagePayload;
|
|
29275
29314
|
} | {
|
|
29276
|
-
|
|
29315
|
+
event: "message.delivered";
|
|
29277
29316
|
data: MessagePayload;
|
|
29278
29317
|
} | {
|
|
29279
|
-
|
|
29318
|
+
event: "message.read";
|
|
29280
29319
|
data: MessagePayload;
|
|
29281
29320
|
} | {
|
|
29282
|
-
|
|
29321
|
+
event: "message.edited";
|
|
29283
29322
|
data: MessagePayload;
|
|
29284
29323
|
} | {
|
|
29285
|
-
|
|
29324
|
+
event: "message.deleted";
|
|
29286
29325
|
data: MessagePayload;
|
|
29287
29326
|
} | {
|
|
29288
|
-
|
|
29327
|
+
event: "message.reaction";
|
|
29289
29328
|
data: MessagePayload;
|
|
29290
29329
|
} | {
|
|
29291
|
-
|
|
29330
|
+
event: "chat.updated";
|
|
29292
29331
|
data: MessagePayload;
|
|
29293
29332
|
} | {
|
|
29294
|
-
|
|
29333
|
+
event: "chat.deleted";
|
|
29295
29334
|
data: MessagePayload;
|
|
29296
29335
|
} | {
|
|
29297
|
-
|
|
29336
|
+
event: "connection.accepted";
|
|
29298
29337
|
data: ConnectionPayload;
|
|
29299
29338
|
} | {
|
|
29300
|
-
|
|
29339
|
+
event: "connection.new";
|
|
29301
29340
|
data: ConnectionPayload;
|
|
29302
29341
|
} | {
|
|
29303
|
-
|
|
29342
|
+
event: "account.created";
|
|
29304
29343
|
data: AccountPayload;
|
|
29305
29344
|
} | {
|
|
29306
|
-
|
|
29345
|
+
event: "account.connected";
|
|
29307
29346
|
data: AccountPayload;
|
|
29308
29347
|
} | {
|
|
29309
|
-
|
|
29348
|
+
event: "account.synced";
|
|
29310
29349
|
data: AccountPayload;
|
|
29311
29350
|
} | {
|
|
29312
|
-
|
|
29351
|
+
event: "account.reconnected";
|
|
29313
29352
|
data: AccountPayload;
|
|
29314
29353
|
} | {
|
|
29315
|
-
|
|
29354
|
+
event: "account.reconnect_needed";
|
|
29316
29355
|
data: AccountPayload;
|
|
29317
29356
|
} | {
|
|
29318
|
-
|
|
29357
|
+
event: "account.creation_failed";
|
|
29319
29358
|
data: AccountPayload;
|
|
29320
29359
|
} | {
|
|
29321
|
-
|
|
29360
|
+
event: "account.disconnected";
|
|
29322
29361
|
data: AccountPayload;
|
|
29323
29362
|
} | {
|
|
29324
|
-
|
|
29363
|
+
event: "account.error";
|
|
29325
29364
|
data: AccountPayload;
|
|
29326
29365
|
} | {
|
|
29327
|
-
|
|
29366
|
+
event: "account.paused";
|
|
29328
29367
|
data: AccountPayload;
|
|
29329
29368
|
} | {
|
|
29330
|
-
|
|
29369
|
+
event: "account.connecting";
|
|
29331
29370
|
data: AccountPayload;
|
|
29332
29371
|
} | {
|
|
29333
|
-
|
|
29372
|
+
event: "account.permission_revoked";
|
|
29334
29373
|
data: AccountPayload;
|
|
29335
29374
|
} | {
|
|
29336
|
-
|
|
29375
|
+
event: "account.initial_sync.running";
|
|
29337
29376
|
data: AccountPayload;
|
|
29338
29377
|
} | {
|
|
29339
|
-
|
|
29378
|
+
event: "account.initial_sync.completed";
|
|
29340
29379
|
data: AccountPayload;
|
|
29341
29380
|
} | {
|
|
29342
|
-
|
|
29381
|
+
event: "account.initial_sync.failed";
|
|
29343
29382
|
data: AccountPayload;
|
|
29344
|
-
};
|
|
29383
|
+
});
|
|
29345
29384
|
/**
|
|
29346
29385
|
* Options for {@link constructEvent}.
|
|
29347
29386
|
*/
|
|
@@ -29386,7 +29425,7 @@ interface ConstructEventOptions {
|
|
|
29386
29425
|
* }
|
|
29387
29426
|
* throw err;
|
|
29388
29427
|
* }
|
|
29389
|
-
* if (event.
|
|
29428
|
+
* if (event.event === 'message.received') { ... }
|
|
29390
29429
|
* res.sendStatus(200);
|
|
29391
29430
|
* });
|
|
29392
29431
|
*
|
|
@@ -29400,4 +29439,4 @@ interface ConstructEventOptions {
|
|
|
29400
29439
|
*/
|
|
29401
29440
|
declare function constructEvent(rawBody: string | Buffer, signatureHeader: string, secret: string, opts?: ConstructEventOptions): Promise<CurviateEvent>;
|
|
29402
29441
|
|
|
29403
|
-
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
|
@@ -2684,12 +2684,27 @@ function verifyAndParse(computedHex, v1, timestamp, bodyStr, replayWindowSecs) {
|
|
|
2684
2684
|
try {
|
|
2685
2685
|
parsed = JSON.parse(bodyStr);
|
|
2686
2686
|
} catch {
|
|
2687
|
-
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
|
+
);
|
|
2688
2691
|
}
|
|
2689
|
-
if (typeof parsed !== "object" || parsed === null ||
|
|
2690
|
-
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
|
+
);
|
|
2691
2705
|
}
|
|
2692
|
-
|
|
2706
|
+
record["event"] = discriminant;
|
|
2707
|
+
return record;
|
|
2693
2708
|
}
|
|
2694
2709
|
async function constructEvent(rawBody, signatureHeader, secret, opts) {
|
|
2695
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"
|