@curviate/sdk 0.37.1 → 0.39.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 CHANGED
@@ -9,6 +9,92 @@ Versioning: semantic. Minor for additive changes, patch for bug fixes; no stabil
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.39.0] - 2026-09-28
13
+
14
+ Fixture and types regenerated against the deployed production document
15
+ (`https://api.curviate.com`, 130 paths, server
16
+ `006f3739c93ff758085dc0ad13ae423bafab4631`).
17
+
18
+ ### Changed
19
+
20
+ - **The retry decision now honours an explicit `retry_likely_to_succeed:
21
+ false`.** A GET on a retryable code (`INTERNAL`, `PLATFORM_ERROR`,
22
+ `PLATFORM_RATE_LIMIT`, `RATE_LIMIT_ACCOUNT`, `RATE_LIMIT_TENANT`) whose
23
+ envelope says `retry_likely_to_succeed: false` is no longer retried, with or
24
+ without a `retry_hint`. The server now sends `false` only as a verdict that
25
+ an unchanged retry fails the same way, and `true` for a failure whose cause
26
+ it cannot see, so this closes the half of the 0.37.1 fix that was deferred.
27
+ A response with no JSON envelope, or no such field, still retries on the
28
+ code table alone. Requires a server that includes the change; against an
29
+ older server, unexpected `INTERNAL` and `PLATFORM_ERROR` failures would stop
30
+ being retried.
31
+ - **`accounts.addSeats()` documents its new failure shapes.** A `502` means
32
+ the purchase failed after today's charge was taken; the charge was refunded
33
+ in full and the seat count was confirmed unchanged, so no seats were added
34
+ and it is safe to retry. A `503 STRIPE_DRIFT_DETECTED` means the seat price
35
+ is misconfigured on our side: nothing was charged, this is not something you
36
+ can fix, and retrying fails the same way until the price is corrected.
37
+ Contact support. Both are generated-type/description additions; no
38
+ resource-method shape changed.
39
+
40
+ ## [0.38.0] - 2026-09-26
41
+
42
+ Fixture and types regenerated against the deployed production document
43
+ (`https://api.curviate.com`, 130 paths, server
44
+ `f06ce7e52877ead27c1cfc62dde311c8cda9a325`). Adds programmatic connect at
45
+ scale: your own end-user id on accounts, tenant-wide account-status webhooks,
46
+ challenge selection on checkpoints, and seat purchase over the API.
47
+
48
+ ### Added
49
+
50
+ - **`accounts.addSeats({ qty })`, `accounts.cancelSeat(seatId)`,
51
+ `accounts.revertSeatCancellation(seatId)`.** Buy seats, schedule a seat's
52
+ end-of-period cancellation, and undo it, without the dashboard. Every
53
+ `addSeats` call buys the seats it asks for, so a repeated call buys again,
54
+ and the SDK never retries it. On `SUBSCRIPTION_BUSY` (503) the purchase could
55
+ not be confirmed: check the seat count with `accounts.listSeats()` before
56
+ trying again. A trialing workspace gets `TRIAL_ACTIVE_SEAT_LIMIT`.
57
+ Their types include the 402 refusals (no subscription, past due, dispute,
58
+ and on add a declined card) and the 503 `SUBSCRIPTION_BUSY`.
59
+ - **`external_id` on accounts.** Pass your own id for the account's end user on
60
+ `auth.intent` or `accounts.update` (`null` clears it). It is returned on
61
+ `accounts.get`/`list`, on the connect responses, and on every `account.*`
62
+ webhook payload (`AccountPayload.external_id`, `null` when unset).
63
+ `accounts.list({ external_id })` returns only that end user's accounts.
64
+ - **`metadata` is stored and read back.** `accounts.update({ metadata })` now
65
+ persists the map (at most 16 keys) and `accounts.get`/`list` return it;
66
+ `null` clears it.
67
+ - **`timezone` and `products` on `auth.intent`.** `timezone` is an IANA zone
68
+ name; `products` narrows the premium products asked for
69
+ (`["sales_navigator"]`, `["recruiter"]`, or `[]`).
70
+ - **Challenge selection.** A checkpoint can now be
71
+ `challenge_type: "challenge_selection"` with a `challenges` list
72
+ (`{ id, label, description }`). Answer it with
73
+ `auth.requestCheckpoint(accountId, { challenge: id })`, which returns the next
74
+ checkpoint.
75
+ - **Tenant-wide account-status webhooks.** `webhooks.create` with
76
+ `source: "account_status"` no longer needs `account_ids`: omit it to cover
77
+ every current and future account. `webhooks.update(id, { account_ids: null })`
78
+ switches an existing one.
79
+
80
+ ### Changed
81
+
82
+ - **`auth.requestCheckpoint` returns `200 | 202`.** Without a body it still
83
+ re-sends and returns `{ resent }`; with `{ challenge }` it returns the next
84
+ checkpoint. Code reading `result.resent` must narrow first
85
+ (`"status" in result` for the 202 checkpoint, `"resent" in result` for the
86
+ 200 re-send; each narrows only its true branch).
87
+ - **Webhook `account_ids` is `string[] | null` on reads.** `null` means a
88
+ tenant-wide `account_status` webhook.
89
+ - **Empty optional text is refused.** An empty `headline` on `users.update`,
90
+ an empty `subject` on `messaging.startChat` and an empty `message` on
91
+ `invites.send` are now rejected with `INVALID_REQUEST`. `bio: ""` is still
92
+ accepted (its type now reads `"" | string`).
93
+ - **`account.restricted` documented as "connected, some actions fail".** The
94
+ event also fires when one LinkedIn product on the account (Sales Navigator,
95
+ Recruiter) is failing, not only for a LinkedIn restriction. Surface it to a
96
+ human; a reconnect may restore a single failing product.
97
+
12
98
  ## [0.37.1] - 2026-09-23
13
99
 
14
100
  Fixture and types regenerated against the deployed production document