@curviate/sdk 0.27.0 → 0.28.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 +42 -0
- package/dist/index.d.ts +22 -11
- package/package.json +1 -1
- package/src/generated/types.ts +22 -11
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,48 @@ Versioning: semantic. Minor for additive changes, patch for bug fixes; no stabil
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.28.0] - 2026-09-07
|
|
11
|
+
|
|
12
|
+
Fixture regenerated against the deployed staging document
|
|
13
|
+
(`https://api.staging.curviate.com`, `server_git_sha 14fa8234...`, 125 paths).
|
|
14
|
+
**BREAKING**: `messaging.searchChats` now rejects a `query` shorter than 3
|
|
15
|
+
characters server-side. Pre-1.0 a breaking change ships as a minor, so a caret
|
|
16
|
+
range on `0.27.x` will not pick this up.
|
|
17
|
+
|
|
18
|
+
### BREAKING
|
|
19
|
+
|
|
20
|
+
- **`searchChats` requires a `query` of at least 3 characters.** A 1-2 character
|
|
21
|
+
term previously returned `200`; it now returns `400 INVALID_REQUEST` with a
|
|
22
|
+
message naming the minimum. The search is served from an index built out of
|
|
23
|
+
overlapping 3-character sequences, so a shorter term cannot use it at all and
|
|
24
|
+
falls back to a scan: measured at 238-292 ms against 4.5 ms for the same term
|
|
25
|
+
one character longer. Returning `200` after 60x the work, with no way for a
|
|
26
|
+
caller to learn why, was the worse contract.
|
|
27
|
+
|
|
28
|
+
The bound is now expressed in the OpenAPI schema (`minLength: 3`) and in the
|
|
29
|
+
generated parameter description. **TypeScript cannot express a string minimum
|
|
30
|
+
length**, so the generated type is still `string`: the constraint is
|
|
31
|
+
documented and enforced at the wire, not by the compiler. Debounce a
|
|
32
|
+
type-ahead to 3 characters rather than relying on types to catch it.
|
|
33
|
+
|
|
34
|
+
`companies.searchChats` is a different endpoint and is unaffected; its
|
|
35
|
+
`query` stays optional and unbounded.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- **`accounts.retrieve` gains `event_log`**: `{ retained, row_cap, at_row_cap }`.
|
|
40
|
+
Reports where the account stands against the retained event log's per-account
|
|
41
|
+
row budget. While `at_row_cap` is true, events are still delivered to any
|
|
42
|
+
registered webhook but are no longer retained, so the events resource has
|
|
43
|
+
stopped being a complete record of what arrived. Additive and always present.
|
|
44
|
+
|
|
45
|
+
- Every string parameter and body field on the surface now publishes its real
|
|
46
|
+
length bounds (`minLength` / `maxLength`) where the server enforces one. This
|
|
47
|
+
was previously emitted only for numbers, so string constraints existed in
|
|
48
|
+
descriptions and nowhere a generated client could read them.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
10
52
|
## [0.27.0] - 2026-09-06
|
|
11
53
|
|
|
12
54
|
Fixture regenerated against the deployed production document
|
package/dist/index.d.ts
CHANGED
|
@@ -2689,7 +2689,7 @@ interface paths {
|
|
|
2689
2689
|
head?: never;
|
|
2690
2690
|
/**
|
|
2691
2691
|
* Update an account's safety policy
|
|
2692
|
-
* @description The single safety-policy write. Send only the fields you are changing: everything you omit is left byte-identical, and sending `null` for a field clears your override and restores the Curviate default. Any limit may be set to any value: Curviate does not clamp, cap or refuse a change on the grounds that the number is unsafe. A value above the Curviate default is reported back in the response, and on every later read, with the default and its source class attached; there is no way to acknowledge it away, and setting the value back to the default removes it. A value that is not a value, such as a negative ceiling or an unknown row name, is a 400. Every field whose value CHANGES is appended to the account's action ledger with the previous value, the new value, the Curviate default, the actor and the time; a field you send whose value already equals its current effective value is not ledgered and is not stored as an override, so reading the policy and sending the document back changes nothing. Six fields on the read are derived rather than configured: `effective_ceiling`, `interface_ceiling`, `effective_interface_ceiling`, `posture_source`, `over_default` and each row's `warm_up_state`. Send them and they are accepted and ignored, never stored and never ledgered, so the document you read can go straight back. To pin a row's ramp, set `warm_up_factor`. `activity_window` is not accepted: send its settable subfields instead, the top-level `timezone` for the zone, and per row `activity_window_start`, `activity_window_end`, `activity_window_timezone` and `activity_window_applies_to`. The 400 this produces names those subfields, not just the refused object. And read `changes nothing` as `changes no limit`: the `posture` fields are OVERRIDES at every scope, so writing back a posture a scope merely inherits PINS it there and appends one ledger entry per pinned scope. That is what stops a later account- or tenant-wide change from moving it. A pin already in place is a no-op. An agent-authenticated write is accepted on exactly the same footing as an operator's. There is no bulk import, file upload or policy template: configuring many rows or many accounts is a loop over this operation. One field is not account-scoped: `tenant_default_posture` sets the default for EVERY account in the tenant, not just the one in the path, which is what makes it a one-call change for a whole workspace of personas. It is reported back at the top of every policy response, so a change to it is visible even on an account that overrides it. One other field is not row-scoped: `limit_profile` selects which of the four Curviate default sets this account's rows resolve from, so it moves the default under every row at once while leaving every value you have configured explicitly exactly as you set it. It is the platform product active on the account, not your Curviate seat entitlement, and the two can disagree: a lapsed subscription leaves the seat untouched. Curviate detects it when the account connects and re-detects it on every reconnect; setting it here is an operator override of that result, and it holds until the next connect. When the seat and the detected product disagree, the detected product wins the numbers and the read reports the disagreement as `seat_tier_mismatch`.
|
|
2692
|
+
* @description The single safety-policy write. Send only the fields you are changing: everything you omit is left byte-identical, and sending `null` for a field clears your override and restores the Curviate default. Any limit may be set to any value: Curviate does not clamp, cap or refuse a change on the grounds that the number is unsafe. A value above the Curviate default is reported back in the response, and on every later read, with the default and its source class attached; there is no way to acknowledge it away, and setting the value back to the default removes it. A value that is not a value, such as a negative ceiling or an unknown row name, is a 400. Every field whose value CHANGES is appended to the account's action ledger with the previous value, the new value, the Curviate default, the actor and the time; a field you send whose value already equals its current effective value is not ledgered and is not stored as an override, so reading the policy and sending the document back changes nothing. Six fields on the read are derived rather than configured: `effective_ceiling`, `interface_ceiling`, `effective_interface_ceiling`, `posture_source`, `over_default` and each row's `warm_up_state`. Send them and they are accepted and ignored, never stored and never ledgered, so the document you read can go straight back. To pin a row's ramp, set `warm_up_factor`. `activity_window` is not accepted: send its settable subfields instead, the top-level `timezone` for the zone, and per row `activity_window_start`, `activity_window_end`, `activity_window_timezone` and `activity_window_applies_to`. The 400 this produces names those subfields, not just the refused object. And read `changes nothing` as `changes no limit`: the `posture` fields are OVERRIDES at every scope, so writing back a posture a scope merely inherits PINS it there and appends one ledger entry per pinned scope. That is what stops a later account- or tenant-wide change from moving it. A pin already in place is a no-op. An agent-authenticated write is accepted on exactly the same footing as an operator's. There is no bulk import, file upload or policy template: configuring many rows or many accounts is a loop over this operation. One field is not account-scoped: `tenant_default_posture` sets the default for EVERY account in the tenant, not just the one in the path, which is what makes it a one-call change for a whole workspace of personas. It is reported back at the top of every policy response, so a change to it is visible even on an account that overrides it. One other field is not row-scoped: `limit_profile` selects which of the four Curviate default sets this account's rows resolve from, so it moves the default under every row at once while leaving every value you have configured explicitly exactly as you set it. It is the platform product active on the account, not your Curviate seat entitlement, and the two can disagree: a lapsed subscription leaves the seat untouched. Curviate detects it when the account connects and re-detects it on every reconnect; setting it here is an operator override of that result, and it holds until the next connect. When the seat and the detected product disagree, the detected product wins the numbers and the read reports the disagreement as `seat_tier_mismatch`. One field on this operation does not configure anything: `clear_halts` lifts the platform pause on the action types you name. When the platform refuses a call on an account, Curviate pauses that action type for the platform's own retry-after or a seeded cooldown, and every later call on it is refused locally without reaching the platform; the account resource reports the live pauses as `quotas[].halt`. Naming an action type here lifts its pause immediately, so the next call goes out. An action type with no active pause is accepted and does nothing, which makes it safe to send for a set you have not checked, and only the ones actually lifted are ledgered, each with the expiry it cut short, the actor and the time, readable afterwards on `GET /v1/{account_id}/safety-events` with `reason: "halt_cleared"`. Clearing disarms nothing: if the platform refuses the account again the pause returns, and a 429 or a refused write returns it for the full cooldown. Clear one when you have reason to believe the refusal was a transient upstream fault rather than the platform pushing back on this account.
|
|
2693
2693
|
*/
|
|
2694
2694
|
patch: operations["patchV1AccountIdSafetyPolicy"];
|
|
2695
2695
|
trace?: never;
|
|
@@ -2703,7 +2703,7 @@ interface paths {
|
|
|
2703
2703
|
};
|
|
2704
2704
|
/**
|
|
2705
2705
|
* List what Curviate refused or warned about
|
|
2706
|
-
* @description Returns this account's safety events, newest first: every action Curviate refused, and every action it let through while flagging that a limit had been crossed. Under the default posture nothing is refused, so everything here is a warning and `blocked` is how you tell the two apart. Each event names the budget row that breached, why, the operation that hit it and when. Filter by `budget_row` for one action type and by `since` / `until` for a period, and page until `cursor` is null. This is a read of what already happened, so it never changes a limit or a count: to change what is refused, update the safety policy. The account resource is the other half of the picture, reporting where each row stands right now rather than what has already been flagged.
|
|
2706
|
+
* @description Returns this account's safety events, newest first: every action Curviate refused, and every action it let through while flagging that a limit had been crossed. Under the default posture nothing is refused, so everything here is a warning and `blocked` is how you tell the two apart. Each event names the budget row that breached, why, the operation that hit it and when. Filter by `budget_row` for one action type and by `since` / `until` for a period, and page until `cursor` is null. This is a read of what already happened, so it never changes a limit or a count: to change what is refused, update the safety policy. The account resource is the other half of the picture, reporting where each row stands right now rather than what has already been flagged. One entry here is not a refusal: `reason: "halt_cleared"` with `blocked: false` records somebody lifting a platform pause early through `clear_halts` on the safety policy, and it sits beside the `rate_limited` entry it lifted so the pause and its end read as one thread.
|
|
2707
2707
|
*/
|
|
2708
2708
|
get: operations["getV1AccountIdSafetyEvents"];
|
|
2709
2709
|
put?: never;
|
|
@@ -12096,7 +12096,7 @@ interface operations {
|
|
|
12096
12096
|
getV1AccountIdChatsSearch: {
|
|
12097
12097
|
parameters: {
|
|
12098
12098
|
query: {
|
|
12099
|
-
/** @description The search term: matches both participant names and message content (e.g. 'sophie keller').
|
|
12099
|
+
/** @description The search term: matches both participant names and message content (e.g. 'sophie keller'). Minimum 3 characters. A shorter term cannot use the search index and is rejected with INVALID_REQUEST. */
|
|
12100
12100
|
query: string;
|
|
12101
12101
|
/** @description Maximum chats to return per page (1-100, default 20). The server may walk a few internal pages to fill one page. */
|
|
12102
12102
|
limit?: number;
|
|
@@ -27899,7 +27899,7 @@ interface operations {
|
|
|
27899
27899
|
};
|
|
27900
27900
|
requestBody?: never;
|
|
27901
27901
|
responses: {
|
|
27902
|
-
/** @description The account's metadata and current state, including the quotas[] budget view (one entry per counted action row for this account, for the current window of that row's grain) account_states[], the platform conditions the account is currently in,
|
|
27902
|
+
/** @description The account's metadata and current state, including the quotas[] budget view (one entry per counted action row for this account, for the current window of that row's grain) account_states[], the platform conditions the account is currently in, activity_window, the hours in which live writes are reported or refused, and event_log, where the account stands against the retained event log's row budget. */
|
|
27903
27903
|
200: {
|
|
27904
27904
|
headers: {
|
|
27905
27905
|
"RateLimit-Policy": components["headers"]["RateLimit-Policy"];
|
|
@@ -27972,7 +27972,7 @@ interface operations {
|
|
|
27972
27972
|
posture: "warn" | "enforce";
|
|
27973
27973
|
/** @description Whether something on this row is configured above Curviate's own default. The safety policy carries the detail: which field, the value, the default and how well calibrated that default is. */
|
|
27974
27974
|
over_default: boolean;
|
|
27975
|
-
/** @description An active pause on this row because the platform refused a recent request on it, or `null`. A halt is not a ceiling: no limit you raise lifts it, and it clears itself when it expires. */
|
|
27975
|
+
/** @description An active pause on this row because the platform refused a recent request on it, or `null`. A halt is not a ceiling: no limit you raise lifts it, and it clears itself when it expires. To lift one before it expires, send this row in `clear_halts` on `PATCH /v1/{account_id}/safety-policy`; that is recorded, and the pause returns if the platform refuses the account again. */
|
|
27976
27976
|
halt: {
|
|
27977
27977
|
/** @description What the platform did: `rate_limited`, `platform_fault`, or `resend_cooldown` (the same invitation was sent too recently). */
|
|
27978
27978
|
reason?: string;
|
|
@@ -27999,6 +27999,15 @@ interface operations {
|
|
|
27999
27999
|
/** @description True when no zone is set, which DISABLES the activity window. Curviate never guesses a zone: a guess eight hours wrong inverts the window, refusing every daytime write and permitting every nocturnal one. If you configured a window and it never fires, this is why. */
|
|
28000
28000
|
timezone_unset?: boolean;
|
|
28001
28001
|
};
|
|
28002
|
+
/** @description Where this account stands against the retained event log's row budget. Events are retained for 24 hours so you can read what the platform sent without running a listener; an account may hold at most row_cap of them at once. While at_row_cap is true, further events for this account are still delivered to any webhook you registered but are NOT retained, so the events resource stops being a complete record of what arrived. The budget is a backstop against a misbehaving upstream, sized so ordinary use never approaches it. */
|
|
28003
|
+
event_log?: {
|
|
28004
|
+
/** @description Events currently held for this account. A level, not a total: retention is 24 hours, so this falls on its own as events age out. */
|
|
28005
|
+
retained?: number;
|
|
28006
|
+
/** @description The maximum this account may hold at once. */
|
|
28007
|
+
row_cap?: number;
|
|
28008
|
+
/** @description True while the cap is biting and incoming events are not being retained. Delivery to a registered webhook is unaffected. */
|
|
28009
|
+
at_row_cap?: boolean;
|
|
28010
|
+
};
|
|
28002
28011
|
safety_warning?: components["schemas"]["SafetyWarning"];
|
|
28003
28012
|
};
|
|
28004
28013
|
};
|
|
@@ -30514,7 +30523,7 @@ interface operations {
|
|
|
30514
30523
|
/** @description IANA zone name the activity window is read in. Null disables the window entirely. */
|
|
30515
30524
|
activity_window_timezone?: string | null;
|
|
30516
30525
|
/**
|
|
30517
|
-
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads as well, which is the setting for a persona that should not be seen browsing at 03:00. It is broader than it sounds: `all` covers every live read, including the ones about the account itself, so a nightly analytics or invitation-backlog poll is refused at 03:00 too. A read Curviate answers from its own store never reaches LinkedIn, so it is never subject to the window under either setting, at any hour; the same read IS covered when the store cannot answer it, or when you ask for it live. Inbound events are never subject to it either.
|
|
30526
|
+
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads as well, which is the setting for a persona that should not be seen browsing at 03:00. It is broader than it sounds: `all` covers every live read, including the ones about the account itself, so a nightly analytics or invitation-backlog poll is refused at 03:00 too. A read Curviate answers from its own store never reaches LinkedIn, so it is never subject to the window under either setting, at any hour; the same read IS covered when the store cannot answer it, or when you ask for it live. Inbound events are never subject to it either. One action set to `all` reaches the whole account's live reads that spend no budget of their own (notifications, profile analytics, SSI, profile visitors, the invitation and saved-list listings): those calls debit no action type, so they have none to read this setting from and take the account-wide answer instead. Reads that DO debit an action type read that action type's own setting.
|
|
30518
30527
|
* @enum {string}
|
|
30519
30528
|
*/
|
|
30520
30529
|
activity_window_applies_to?: "writes" | "all";
|
|
@@ -30612,6 +30621,8 @@ interface operations {
|
|
|
30612
30621
|
* @enum {string|null}
|
|
30613
30622
|
*/
|
|
30614
30623
|
tenant_default_posture?: "warn" | "enforce" | null;
|
|
30624
|
+
/** @description Lift the platform pause on these action types now, instead of waiting for it to expire. When the platform refuses a call on an account (a rate limit, a server error on a budgeted route, an invitation resend cooldown), Curviate pauses that action type for the platform's own retry-after or a seeded cooldown, and every later call on it is refused locally without reaching the platform. Naming an action type here clears that pause: the next call goes out. Read `quotas[].halt` on the account to see which action types are paused and for how long. A type with no active pause is accepted and does nothing, so this is safe to send for a set you have not checked. Clearing is recorded in the account's ledger with the expiry it cut short, who cleared it and when, and it appears on the safety-events surface. It does not disarm anything: if the platform refuses the account again, the pause comes straight back, longer than the one you cleared where the platform says so. Clear a pause when you have reason to believe the refusal was a transient upstream fault rather than the platform pushing back on this account; clearing one and calling straight back into a real rate limit is itself how accounts get restricted. */
|
|
30625
|
+
clear_halts?: ("connection_requests_with_note" | "connection_requests_no_note" | "messages_first_degree" | "inmail" | "open_profile_inmail" | "profile_views" | "search" | "comments" | "post_likes" | "follows" | "content_poll" | "job_poll" | "posts" | "endorsements" | "invite_responses" | "withdrawal_sweep")[];
|
|
30615
30626
|
/**
|
|
30616
30627
|
* @description This account's posture default, overriding the tenant default for this account only. Null clears the override.
|
|
30617
30628
|
* @enum {string|null}
|
|
@@ -30651,7 +30662,7 @@ interface operations {
|
|
|
30651
30662
|
/** @description IANA zone name the activity window is read in, e.g. `Europe/Berlin`. Must be a real zone; anything else is a 400. Null DISABLES the activity window: a guessed zone inverts it, which is worse than not having one. */
|
|
30652
30663
|
activity_window_timezone?: string | null;
|
|
30653
30664
|
/**
|
|
30654
|
-
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads. A read Curviate answers from its own store never reaches LinkedIn and so is never covered; the same read IS covered when the store cannot answer it, or when you ask for it live. Stored reads and inbound events are never subject to the window under either setting, at any hour.
|
|
30665
|
+
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads. A read Curviate answers from its own store never reaches LinkedIn and so is never covered; the same read IS covered when the store cannot answer it, or when you ask for it live. Stored reads and inbound events are never subject to the window under either setting, at any hour. One action set to `all` reaches the whole account's live reads that spend no budget of their own (notifications, profile analytics, SSI, profile visitors, the invitation and saved-list listings): those calls debit no action type, so they have none to read this setting from and take the account-wide answer instead. Reads that DO debit an action type read that action type's own setting.
|
|
30655
30666
|
* @enum {string|null}
|
|
30656
30667
|
*/
|
|
30657
30668
|
activity_window_applies_to?: "writes" | "all" | null;
|
|
@@ -30800,7 +30811,7 @@ interface operations {
|
|
|
30800
30811
|
/** @description IANA zone name the activity window is read in. Null disables the window entirely. */
|
|
30801
30812
|
activity_window_timezone?: string | null;
|
|
30802
30813
|
/**
|
|
30803
|
-
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads as well, which is the setting for a persona that should not be seen browsing at 03:00. It is broader than it sounds: `all` covers every live read, including the ones about the account itself, so a nightly analytics or invitation-backlog poll is refused at 03:00 too. A read Curviate answers from its own store never reaches LinkedIn, so it is never subject to the window under either setting, at any hour; the same read IS covered when the store cannot answer it, or when you ask for it live. Inbound events are never subject to it either.
|
|
30814
|
+
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads as well, which is the setting for a persona that should not be seen browsing at 03:00. It is broader than it sounds: `all` covers every live read, including the ones about the account itself, so a nightly analytics or invitation-backlog poll is refused at 03:00 too. A read Curviate answers from its own store never reaches LinkedIn, so it is never subject to the window under either setting, at any hour; the same read IS covered when the store cannot answer it, or when you ask for it live. Inbound events are never subject to it either. One action set to `all` reaches the whole account's live reads that spend no budget of their own (notifications, profile analytics, SSI, profile visitors, the invitation and saved-list listings): those calls debit no action type, so they have none to read this setting from and take the account-wide answer instead. Reads that DO debit an action type read that action type's own setting.
|
|
30804
30815
|
* @enum {string}
|
|
30805
30816
|
*/
|
|
30806
30817
|
activity_window_applies_to?: "writes" | "all";
|
|
@@ -30943,11 +30954,11 @@ interface operations {
|
|
|
30943
30954
|
*/
|
|
30944
30955
|
budget_row: "connection_requests_with_note" | "connection_requests_no_note" | "messages_first_degree" | "inmail" | "open_profile_inmail" | "profile_views" | "search" | "comments" | "post_likes" | "follows" | "content_poll" | "job_poll" | "posts" | "endorsements" | "invite_responses" | "withdrawal_sweep" | "total_actions" | "pending_invites" | "*";
|
|
30945
30956
|
/**
|
|
30946
|
-
* @description Which rule flagged it, and each one calls for a different response. `budget_exhausted`: the account reached the ceiling configured for that row, which you can raise on the safety policy. `activity_window`: the account was acting outside its configured activity window, so no ceiling was the constraint. Wait for the window to open, move `activity_window_start` or `activity_window_end`, or check `activity_window_timezone` is the zone you meant. `rate_limited`: the platform itself refused this account on that row recently and Curviate is holding the row until the pause expires, which
|
|
30957
|
+
* @description Which rule flagged it, and each one calls for a different response. `budget_exhausted`: the account reached the ceiling configured for that row, which you can raise on the safety policy. `activity_window`: the account was acting outside its configured activity window, so no ceiling was the constraint. Wait for the window to open, move `activity_window_start` or `activity_window_end`, or check `activity_window_timezone` is the zone you meant. `rate_limited`: the platform itself refused this account on that row recently and Curviate is holding the row until the pause expires. No ceiling you raise lifts it; the one thing that does is `clear_halts` on the safety policy, which lifts it deliberately and records that it was lifted. `halt_cleared` is the odd one out and the only entry that is not a refusal: somebody lifted one of those platform pauses early through `clear_halts` on the safety policy, so the row was open again from that instant. It carries `blocked: false` and its `method` is `update_safety_policy` rather than the operation that breached. Read it beside the `rate_limited` entry it lifts: the pause and its lifting are one thread, and an entry list that showed only the first would report a row as still paused.
|
|
30947
30958
|
* @enum {string}
|
|
30948
30959
|
*/
|
|
30949
|
-
reason: "budget_exhausted" | "activity_window" | "rate_limited";
|
|
30950
|
-
/** @description Whether the action was stopped. `false` is a warning: the action went through, and this record is the only lasting trace that it crossed a limit. Under the default `warn` posture every event is a warning, which is what makes reading this surface the point of running it. */
|
|
30960
|
+
reason: "budget_exhausted" | "activity_window" | "rate_limited" | "halt_cleared";
|
|
30961
|
+
/** @description Whether the action was stopped. `false` is a warning: the action went through, and this record is the only lasting trace that it crossed a limit. Under the default `warn` posture every event is a warning, which is what makes reading this surface the point of running it. A `halt_cleared` entry is also `false`, for a different reason: it stopped nothing, it lifted a stop. */
|
|
30951
30962
|
blocked: boolean;
|
|
30952
30963
|
/** @description The operation the caller was running when it breached. */
|
|
30953
30964
|
method: string;
|
package/package.json
CHANGED
package/src/generated/types.ts
CHANGED
|
@@ -2591,7 +2591,7 @@ export interface paths {
|
|
|
2591
2591
|
head?: never;
|
|
2592
2592
|
/**
|
|
2593
2593
|
* Update an account's safety policy
|
|
2594
|
-
* @description The single safety-policy write. Send only the fields you are changing: everything you omit is left byte-identical, and sending `null` for a field clears your override and restores the Curviate default. Any limit may be set to any value: Curviate does not clamp, cap or refuse a change on the grounds that the number is unsafe. A value above the Curviate default is reported back in the response, and on every later read, with the default and its source class attached; there is no way to acknowledge it away, and setting the value back to the default removes it. A value that is not a value, such as a negative ceiling or an unknown row name, is a 400. Every field whose value CHANGES is appended to the account's action ledger with the previous value, the new value, the Curviate default, the actor and the time; a field you send whose value already equals its current effective value is not ledgered and is not stored as an override, so reading the policy and sending the document back changes nothing. Six fields on the read are derived rather than configured: `effective_ceiling`, `interface_ceiling`, `effective_interface_ceiling`, `posture_source`, `over_default` and each row's `warm_up_state`. Send them and they are accepted and ignored, never stored and never ledgered, so the document you read can go straight back. To pin a row's ramp, set `warm_up_factor`. `activity_window` is not accepted: send its settable subfields instead, the top-level `timezone` for the zone, and per row `activity_window_start`, `activity_window_end`, `activity_window_timezone` and `activity_window_applies_to`. The 400 this produces names those subfields, not just the refused object. And read `changes nothing` as `changes no limit`: the `posture` fields are OVERRIDES at every scope, so writing back a posture a scope merely inherits PINS it there and appends one ledger entry per pinned scope. That is what stops a later account- or tenant-wide change from moving it. A pin already in place is a no-op. An agent-authenticated write is accepted on exactly the same footing as an operator's. There is no bulk import, file upload or policy template: configuring many rows or many accounts is a loop over this operation. One field is not account-scoped: `tenant_default_posture` sets the default for EVERY account in the tenant, not just the one in the path, which is what makes it a one-call change for a whole workspace of personas. It is reported back at the top of every policy response, so a change to it is visible even on an account that overrides it. One other field is not row-scoped: `limit_profile` selects which of the four Curviate default sets this account's rows resolve from, so it moves the default under every row at once while leaving every value you have configured explicitly exactly as you set it. It is the platform product active on the account, not your Curviate seat entitlement, and the two can disagree: a lapsed subscription leaves the seat untouched. Curviate detects it when the account connects and re-detects it on every reconnect; setting it here is an operator override of that result, and it holds until the next connect. When the seat and the detected product disagree, the detected product wins the numbers and the read reports the disagreement as `seat_tier_mismatch`.
|
|
2594
|
+
* @description The single safety-policy write. Send only the fields you are changing: everything you omit is left byte-identical, and sending `null` for a field clears your override and restores the Curviate default. Any limit may be set to any value: Curviate does not clamp, cap or refuse a change on the grounds that the number is unsafe. A value above the Curviate default is reported back in the response, and on every later read, with the default and its source class attached; there is no way to acknowledge it away, and setting the value back to the default removes it. A value that is not a value, such as a negative ceiling or an unknown row name, is a 400. Every field whose value CHANGES is appended to the account's action ledger with the previous value, the new value, the Curviate default, the actor and the time; a field you send whose value already equals its current effective value is not ledgered and is not stored as an override, so reading the policy and sending the document back changes nothing. Six fields on the read are derived rather than configured: `effective_ceiling`, `interface_ceiling`, `effective_interface_ceiling`, `posture_source`, `over_default` and each row's `warm_up_state`. Send them and they are accepted and ignored, never stored and never ledgered, so the document you read can go straight back. To pin a row's ramp, set `warm_up_factor`. `activity_window` is not accepted: send its settable subfields instead, the top-level `timezone` for the zone, and per row `activity_window_start`, `activity_window_end`, `activity_window_timezone` and `activity_window_applies_to`. The 400 this produces names those subfields, not just the refused object. And read `changes nothing` as `changes no limit`: the `posture` fields are OVERRIDES at every scope, so writing back a posture a scope merely inherits PINS it there and appends one ledger entry per pinned scope. That is what stops a later account- or tenant-wide change from moving it. A pin already in place is a no-op. An agent-authenticated write is accepted on exactly the same footing as an operator's. There is no bulk import, file upload or policy template: configuring many rows or many accounts is a loop over this operation. One field is not account-scoped: `tenant_default_posture` sets the default for EVERY account in the tenant, not just the one in the path, which is what makes it a one-call change for a whole workspace of personas. It is reported back at the top of every policy response, so a change to it is visible even on an account that overrides it. One other field is not row-scoped: `limit_profile` selects which of the four Curviate default sets this account's rows resolve from, so it moves the default under every row at once while leaving every value you have configured explicitly exactly as you set it. It is the platform product active on the account, not your Curviate seat entitlement, and the two can disagree: a lapsed subscription leaves the seat untouched. Curviate detects it when the account connects and re-detects it on every reconnect; setting it here is an operator override of that result, and it holds until the next connect. When the seat and the detected product disagree, the detected product wins the numbers and the read reports the disagreement as `seat_tier_mismatch`. One field on this operation does not configure anything: `clear_halts` lifts the platform pause on the action types you name. When the platform refuses a call on an account, Curviate pauses that action type for the platform's own retry-after or a seeded cooldown, and every later call on it is refused locally without reaching the platform; the account resource reports the live pauses as `quotas[].halt`. Naming an action type here lifts its pause immediately, so the next call goes out. An action type with no active pause is accepted and does nothing, which makes it safe to send for a set you have not checked, and only the ones actually lifted are ledgered, each with the expiry it cut short, the actor and the time, readable afterwards on `GET /v1/{account_id}/safety-events` with `reason: "halt_cleared"`. Clearing disarms nothing: if the platform refuses the account again the pause returns, and a 429 or a refused write returns it for the full cooldown. Clear one when you have reason to believe the refusal was a transient upstream fault rather than the platform pushing back on this account.
|
|
2595
2595
|
*/
|
|
2596
2596
|
patch: operations["patchV1AccountIdSafetyPolicy"];
|
|
2597
2597
|
trace?: never;
|
|
@@ -2605,7 +2605,7 @@ export interface paths {
|
|
|
2605
2605
|
};
|
|
2606
2606
|
/**
|
|
2607
2607
|
* List what Curviate refused or warned about
|
|
2608
|
-
* @description Returns this account's safety events, newest first: every action Curviate refused, and every action it let through while flagging that a limit had been crossed. Under the default posture nothing is refused, so everything here is a warning and `blocked` is how you tell the two apart. Each event names the budget row that breached, why, the operation that hit it and when. Filter by `budget_row` for one action type and by `since` / `until` for a period, and page until `cursor` is null. This is a read of what already happened, so it never changes a limit or a count: to change what is refused, update the safety policy. The account resource is the other half of the picture, reporting where each row stands right now rather than what has already been flagged.
|
|
2608
|
+
* @description Returns this account's safety events, newest first: every action Curviate refused, and every action it let through while flagging that a limit had been crossed. Under the default posture nothing is refused, so everything here is a warning and `blocked` is how you tell the two apart. Each event names the budget row that breached, why, the operation that hit it and when. Filter by `budget_row` for one action type and by `since` / `until` for a period, and page until `cursor` is null. This is a read of what already happened, so it never changes a limit or a count: to change what is refused, update the safety policy. The account resource is the other half of the picture, reporting where each row stands right now rather than what has already been flagged. One entry here is not a refusal: `reason: "halt_cleared"` with `blocked: false` records somebody lifting a platform pause early through `clear_halts` on the safety policy, and it sits beside the `rate_limited` entry it lifted so the pause and its end read as one thread.
|
|
2609
2609
|
*/
|
|
2610
2610
|
get: operations["getV1AccountIdSafetyEvents"];
|
|
2611
2611
|
put?: never;
|
|
@@ -12000,7 +12000,7 @@ export interface operations {
|
|
|
12000
12000
|
getV1AccountIdChatsSearch: {
|
|
12001
12001
|
parameters: {
|
|
12002
12002
|
query: {
|
|
12003
|
-
/** @description The search term: matches both participant names and message content (e.g. 'sophie keller').
|
|
12003
|
+
/** @description The search term: matches both participant names and message content (e.g. 'sophie keller'). Minimum 3 characters. A shorter term cannot use the search index and is rejected with INVALID_REQUEST. */
|
|
12004
12004
|
query: string;
|
|
12005
12005
|
/** @description Maximum chats to return per page (1-100, default 20). The server may walk a few internal pages to fill one page. */
|
|
12006
12006
|
limit?: number;
|
|
@@ -27803,7 +27803,7 @@ export interface operations {
|
|
|
27803
27803
|
};
|
|
27804
27804
|
requestBody?: never;
|
|
27805
27805
|
responses: {
|
|
27806
|
-
/** @description The account's metadata and current state, including the quotas[] budget view (one entry per counted action row for this account, for the current window of that row's grain) account_states[], the platform conditions the account is currently in,
|
|
27806
|
+
/** @description The account's metadata and current state, including the quotas[] budget view (one entry per counted action row for this account, for the current window of that row's grain) account_states[], the platform conditions the account is currently in, activity_window, the hours in which live writes are reported or refused, and event_log, where the account stands against the retained event log's row budget. */
|
|
27807
27807
|
200: {
|
|
27808
27808
|
headers: {
|
|
27809
27809
|
"RateLimit-Policy": components["headers"]["RateLimit-Policy"];
|
|
@@ -27876,7 +27876,7 @@ export interface operations {
|
|
|
27876
27876
|
posture: "warn" | "enforce";
|
|
27877
27877
|
/** @description Whether something on this row is configured above Curviate's own default. The safety policy carries the detail: which field, the value, the default and how well calibrated that default is. */
|
|
27878
27878
|
over_default: boolean;
|
|
27879
|
-
/** @description An active pause on this row because the platform refused a recent request on it, or `null`. A halt is not a ceiling: no limit you raise lifts it, and it clears itself when it expires. */
|
|
27879
|
+
/** @description An active pause on this row because the platform refused a recent request on it, or `null`. A halt is not a ceiling: no limit you raise lifts it, and it clears itself when it expires. To lift one before it expires, send this row in `clear_halts` on `PATCH /v1/{account_id}/safety-policy`; that is recorded, and the pause returns if the platform refuses the account again. */
|
|
27880
27880
|
halt: {
|
|
27881
27881
|
/** @description What the platform did: `rate_limited`, `platform_fault`, or `resend_cooldown` (the same invitation was sent too recently). */
|
|
27882
27882
|
reason?: string;
|
|
@@ -27903,6 +27903,15 @@ export interface operations {
|
|
|
27903
27903
|
/** @description True when no zone is set, which DISABLES the activity window. Curviate never guesses a zone: a guess eight hours wrong inverts the window, refusing every daytime write and permitting every nocturnal one. If you configured a window and it never fires, this is why. */
|
|
27904
27904
|
timezone_unset?: boolean;
|
|
27905
27905
|
};
|
|
27906
|
+
/** @description Where this account stands against the retained event log's row budget. Events are retained for 24 hours so you can read what the platform sent without running a listener; an account may hold at most row_cap of them at once. While at_row_cap is true, further events for this account are still delivered to any webhook you registered but are NOT retained, so the events resource stops being a complete record of what arrived. The budget is a backstop against a misbehaving upstream, sized so ordinary use never approaches it. */
|
|
27907
|
+
event_log?: {
|
|
27908
|
+
/** @description Events currently held for this account. A level, not a total: retention is 24 hours, so this falls on its own as events age out. */
|
|
27909
|
+
retained?: number;
|
|
27910
|
+
/** @description The maximum this account may hold at once. */
|
|
27911
|
+
row_cap?: number;
|
|
27912
|
+
/** @description True while the cap is biting and incoming events are not being retained. Delivery to a registered webhook is unaffected. */
|
|
27913
|
+
at_row_cap?: boolean;
|
|
27914
|
+
};
|
|
27906
27915
|
safety_warning?: components["schemas"]["SafetyWarning"];
|
|
27907
27916
|
};
|
|
27908
27917
|
};
|
|
@@ -30418,7 +30427,7 @@ export interface operations {
|
|
|
30418
30427
|
/** @description IANA zone name the activity window is read in. Null disables the window entirely. */
|
|
30419
30428
|
activity_window_timezone?: string | null;
|
|
30420
30429
|
/**
|
|
30421
|
-
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads as well, which is the setting for a persona that should not be seen browsing at 03:00. It is broader than it sounds: `all` covers every live read, including the ones about the account itself, so a nightly analytics or invitation-backlog poll is refused at 03:00 too. A read Curviate answers from its own store never reaches LinkedIn, so it is never subject to the window under either setting, at any hour; the same read IS covered when the store cannot answer it, or when you ask for it live. Inbound events are never subject to it either.
|
|
30430
|
+
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads as well, which is the setting for a persona that should not be seen browsing at 03:00. It is broader than it sounds: `all` covers every live read, including the ones about the account itself, so a nightly analytics or invitation-backlog poll is refused at 03:00 too. A read Curviate answers from its own store never reaches LinkedIn, so it is never subject to the window under either setting, at any hour; the same read IS covered when the store cannot answer it, or when you ask for it live. Inbound events are never subject to it either. One action set to `all` reaches the whole account's live reads that spend no budget of their own (notifications, profile analytics, SSI, profile visitors, the invitation and saved-list listings): those calls debit no action type, so they have none to read this setting from and take the account-wide answer instead. Reads that DO debit an action type read that action type's own setting.
|
|
30422
30431
|
* @enum {string}
|
|
30423
30432
|
*/
|
|
30424
30433
|
activity_window_applies_to?: "writes" | "all";
|
|
@@ -30516,6 +30525,8 @@ export interface operations {
|
|
|
30516
30525
|
* @enum {string|null}
|
|
30517
30526
|
*/
|
|
30518
30527
|
tenant_default_posture?: "warn" | "enforce" | null;
|
|
30528
|
+
/** @description Lift the platform pause on these action types now, instead of waiting for it to expire. When the platform refuses a call on an account (a rate limit, a server error on a budgeted route, an invitation resend cooldown), Curviate pauses that action type for the platform's own retry-after or a seeded cooldown, and every later call on it is refused locally without reaching the platform. Naming an action type here clears that pause: the next call goes out. Read `quotas[].halt` on the account to see which action types are paused and for how long. A type with no active pause is accepted and does nothing, so this is safe to send for a set you have not checked. Clearing is recorded in the account's ledger with the expiry it cut short, who cleared it and when, and it appears on the safety-events surface. It does not disarm anything: if the platform refuses the account again, the pause comes straight back, longer than the one you cleared where the platform says so. Clear a pause when you have reason to believe the refusal was a transient upstream fault rather than the platform pushing back on this account; clearing one and calling straight back into a real rate limit is itself how accounts get restricted. */
|
|
30529
|
+
clear_halts?: ("connection_requests_with_note" | "connection_requests_no_note" | "messages_first_degree" | "inmail" | "open_profile_inmail" | "profile_views" | "search" | "comments" | "post_likes" | "follows" | "content_poll" | "job_poll" | "posts" | "endorsements" | "invite_responses" | "withdrawal_sweep")[];
|
|
30519
30530
|
/**
|
|
30520
30531
|
* @description This account's posture default, overriding the tenant default for this account only. Null clears the override.
|
|
30521
30532
|
* @enum {string|null}
|
|
@@ -30555,7 +30566,7 @@ export interface operations {
|
|
|
30555
30566
|
/** @description IANA zone name the activity window is read in, e.g. `Europe/Berlin`. Must be a real zone; anything else is a 400. Null DISABLES the activity window: a guessed zone inverts it, which is worse than not having one. */
|
|
30556
30567
|
activity_window_timezone?: string | null;
|
|
30557
30568
|
/**
|
|
30558
|
-
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads. A read Curviate answers from its own store never reaches LinkedIn and so is never covered; the same read IS covered when the store cannot answer it, or when you ask for it live. Stored reads and inbound events are never subject to the window under either setting, at any hour.
|
|
30569
|
+
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads. A read Curviate answers from its own store never reaches LinkedIn and so is never covered; the same read IS covered when the store cannot answer it, or when you ask for it live. Stored reads and inbound events are never subject to the window under either setting, at any hour. One action set to `all` reaches the whole account's live reads that spend no budget of their own (notifications, profile analytics, SSI, profile visitors, the invitation and saved-list listings): those calls debit no action type, so they have none to read this setting from and take the account-wide answer instead. Reads that DO debit an action type read that action type's own setting.
|
|
30559
30570
|
* @enum {string|null}
|
|
30560
30571
|
*/
|
|
30561
30572
|
activity_window_applies_to?: "writes" | "all" | null;
|
|
@@ -30704,7 +30715,7 @@ export interface operations {
|
|
|
30704
30715
|
/** @description IANA zone name the activity window is read in. Null disables the window entirely. */
|
|
30705
30716
|
activity_window_timezone?: string | null;
|
|
30706
30717
|
/**
|
|
30707
|
-
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads as well, which is the setting for a persona that should not be seen browsing at 03:00. It is broader than it sounds: `all` covers every live read, including the ones about the account itself, so a nightly analytics or invitation-backlog poll is refused at 03:00 too. A read Curviate answers from its own store never reaches LinkedIn, so it is never subject to the window under either setting, at any hour; the same read IS covered when the store cannot answer it, or when you ask for it live. Inbound events are never subject to it either.
|
|
30718
|
+
* @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads as well, which is the setting for a persona that should not be seen browsing at 03:00. It is broader than it sounds: `all` covers every live read, including the ones about the account itself, so a nightly analytics or invitation-backlog poll is refused at 03:00 too. A read Curviate answers from its own store never reaches LinkedIn, so it is never subject to the window under either setting, at any hour; the same read IS covered when the store cannot answer it, or when you ask for it live. Inbound events are never subject to it either. One action set to `all` reaches the whole account's live reads that spend no budget of their own (notifications, profile analytics, SSI, profile visitors, the invitation and saved-list listings): those calls debit no action type, so they have none to read this setting from and take the account-wide answer instead. Reads that DO debit an action type read that action type's own setting.
|
|
30708
30719
|
* @enum {string}
|
|
30709
30720
|
*/
|
|
30710
30721
|
activity_window_applies_to?: "writes" | "all";
|
|
@@ -30847,11 +30858,11 @@ export interface operations {
|
|
|
30847
30858
|
*/
|
|
30848
30859
|
budget_row: "connection_requests_with_note" | "connection_requests_no_note" | "messages_first_degree" | "inmail" | "open_profile_inmail" | "profile_views" | "search" | "comments" | "post_likes" | "follows" | "content_poll" | "job_poll" | "posts" | "endorsements" | "invite_responses" | "withdrawal_sweep" | "total_actions" | "pending_invites" | "*";
|
|
30849
30860
|
/**
|
|
30850
|
-
* @description Which rule flagged it, and each one calls for a different response. `budget_exhausted`: the account reached the ceiling configured for that row, which you can raise on the safety policy. `activity_window`: the account was acting outside its configured activity window, so no ceiling was the constraint. Wait for the window to open, move `activity_window_start` or `activity_window_end`, or check `activity_window_timezone` is the zone you meant. `rate_limited`: the platform itself refused this account on that row recently and Curviate is holding the row until the pause expires, which
|
|
30861
|
+
* @description Which rule flagged it, and each one calls for a different response. `budget_exhausted`: the account reached the ceiling configured for that row, which you can raise on the safety policy. `activity_window`: the account was acting outside its configured activity window, so no ceiling was the constraint. Wait for the window to open, move `activity_window_start` or `activity_window_end`, or check `activity_window_timezone` is the zone you meant. `rate_limited`: the platform itself refused this account on that row recently and Curviate is holding the row until the pause expires. No ceiling you raise lifts it; the one thing that does is `clear_halts` on the safety policy, which lifts it deliberately and records that it was lifted. `halt_cleared` is the odd one out and the only entry that is not a refusal: somebody lifted one of those platform pauses early through `clear_halts` on the safety policy, so the row was open again from that instant. It carries `blocked: false` and its `method` is `update_safety_policy` rather than the operation that breached. Read it beside the `rate_limited` entry it lifts: the pause and its lifting are one thread, and an entry list that showed only the first would report a row as still paused.
|
|
30851
30862
|
* @enum {string}
|
|
30852
30863
|
*/
|
|
30853
|
-
reason: "budget_exhausted" | "activity_window" | "rate_limited";
|
|
30854
|
-
/** @description Whether the action was stopped. `false` is a warning: the action went through, and this record is the only lasting trace that it crossed a limit. Under the default `warn` posture every event is a warning, which is what makes reading this surface the point of running it. */
|
|
30864
|
+
reason: "budget_exhausted" | "activity_window" | "rate_limited" | "halt_cleared";
|
|
30865
|
+
/** @description Whether the action was stopped. `false` is a warning: the action went through, and this record is the only lasting trace that it crossed a limit. Under the default `warn` posture every event is a warning, which is what makes reading this surface the point of running it. A `halt_cleared` entry is also `false`, for a different reason: it stopped nothing, it lifted a stop. */
|
|
30855
30866
|
blocked: boolean;
|
|
30856
30867
|
/** @description The operation the caller was running when it breached. */
|
|
30857
30868
|
method: string;
|