@curviate/sdk 0.25.0 → 0.27.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/dist/index.d.ts CHANGED
@@ -2611,7 +2611,7 @@ interface paths {
2611
2611
  };
2612
2612
  /**
2613
2613
  * List webhook event types
2614
- * @description Returns the complete canonical event catalogue (28 events) grouped by source: messaging (8), user (2), account_status (15), plus 3 tier-gated events. A local catalogue read: no platform call is made.
2614
+ * @description Returns the complete canonical event catalogue (27 events) grouped by source: messaging (7), user (2), account_status (15), plus 3 tier-gated events. A local catalogue read: no platform call is made.
2615
2615
  */
2616
2616
  get: operations["getV1WebhooksEvents"];
2617
2617
  put?: never;
@@ -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. Four fields on the read are derived rather than configured: `effective_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, which for the zone is the top-level `timezone`. 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`.
2693
2693
  */
2694
2694
  patch: operations["patchV1AccountIdSafetyPolicy"];
2695
2695
  trace?: never;
@@ -2747,9 +2747,9 @@ interface components {
2747
2747
  * @enum {string}
2748
2748
  */
2749
2749
  required_tier?: "core" | "sales_nav" | "recruiter";
2750
- /** @description Present on a PLATFORM_RATE_LIMIT raised because one account-safety budget row is paused: LinkedIn refused a recent call on that row, so this one was refused locally without reaching LinkedIn. Names the paused row (for example profile_views, connection_requests_no_note). The pause is scoped to this row on this account; every other row keeps working. Absent on every other rate limit. Also present on BUDGET_EXHAUSTED, where it names the row that hit its CEILING rather than one LinkedIn paused: read the code to tell the two apart, because the recovery differs. */
2751
- row?: string;
2752
- /** @description Present on BUDGET_EXHAUSTED: when this row's budget frees up, as an absolute instant rather than a duration, so it stays true however long you hold it. Null for the pending_invites row, whose backlog falls when invitations are accepted or withdrawn rather than at any window boundary, so there is no instant to name. */
2750
+ /** @description Present on a PLATFORM_RATE_LIMIT raised because one account-safety budget row is paused: LinkedIn refused a recent call on that row, so this one was refused locally without reaching LinkedIn. Names the paused row (for example profile_views, connection_requests_no_note). The pause is scoped to this row on this account; every other row keeps working. Absent on every other rate limit. Also present on BUDGET_EXHAUSTED, where it names the row that hit its CEILING rather than one LinkedIn paused: read the code to tell the two apart, because the recovery differs. Null on a BUDGET_EXHAUSTED whose reason is activity_window and whose action spends no budget of its own, because there is no row to name; hint.parameter still names the setting to change. Never null on a rate limit. */
2751
+ row?: string | null;
2752
+ /** @description Present on BUDGET_EXHAUSTED: the instant the refusal lifts, as an absolute instant rather than a duration, so it stays true however long you hold it. It is the window roll on a ceiling refusal and the next window open on an activity-window one. It is null in the two cases where no clock frees the account: the pending_invites gauge, whose backlog falls when invitations are accepted or withdrawn, and an InMail credit exhaustion (row inmail), which LinkedIn regrants on a schedule this product cannot read. */
2753
2753
  reset_at?: string | null;
2754
2754
  /** @description Present on BUDGET_EXHAUSTED: the exact setting to change, as a field rather than as prose. parameter is addressable on PATCH /v1/{account_id}/safety-policy, so an agent can decide between waiting until reset_at, escalating to a human, and reconfiguring, without parsing the message. */
2755
2755
  hint?: {
@@ -2799,27 +2799,27 @@ interface components {
2799
2799
  }[];
2800
2800
  };
2801
2801
  /**
2802
- * @description Present on a successful response when this account crossed an account-safety ceiling while the affected budget row is on the default warn posture. The action still happened. Field-identical to the BUDGET_EXHAUSTED error body except that blocked is false, so one branch handles both postures and switching the account to enforce is a configuration change rather than a client rewrite.
2802
+ * @description Present on a successful response when this account crossed an account-safety ceiling while the affected budget row is on the default warn posture. The action still happened. Field-identical to the BUDGET_EXHAUSTED error body except that blocked is false and hint.message describes the outcome, so one branch handles both postures and switching the account to enforce is a configuration change rather than a client rewrite.
2803
2803
  * @example {
2804
2804
  * "row": "profile_views",
2805
2805
  * "reset_at": "2026-09-05T00:00:00.000Z",
2806
2806
  * "hint": {
2807
2807
  * "parameter": "profile_views.ceiling",
2808
- * "message": "This account is at its configured ceiling for profile_views."
2808
+ * "message": "This account is at its ceiling for profile_views. This action went through because profile_views.posture is warn, and it counted: 101 of 100 this window. Raise profile_views.ceiling, or wait for the window to reset at 2026-09-05T00:00:00.000Z."
2809
2809
  * },
2810
2810
  * "reason": "ceiling",
2811
2811
  * "blocked": false
2812
2812
  * }
2813
2813
  */
2814
2814
  SafetyWarning: {
2815
- /** @description The budget row that breached, for example profile_views or pending_invites. */
2816
- row: string;
2817
- /** @description When the row frees up, as an absolute instant. Null for the pending_invites gauge. */
2815
+ /** @description The budget row that breached, for example profile_views or pending_invites. Null when the breach is not about a row: an activity_window warning on an action that spends no budget of its own (editing a message, dismissing a notification, a Recruiter or Sales Navigator admin action) is still governed by the hours the account works in. Read hint.parameter for what to change; whenever this is null it names posture, because the activity window edges are set per action type and this action has none, so the levers that reach it are the account timezone and posture. */
2816
+ row: string | null;
2817
+ /** @description The instant the refusal lifts: the window roll on a ceiling refusal, the next window open on an activity-window one. Null in the two cases no clock frees, the pending_invites gauge and InMail credits (row inmail). */
2818
2818
  reset_at: string | null;
2819
2819
  hint: {
2820
2820
  /** @description The settable parameter on PATCH /v1/{account_id}/safety-policy. */
2821
2821
  parameter: string;
2822
- /** @description What the condition is and what changing that parameter would do. */
2822
+ /** @description What the condition is and what changing that parameter would do. This is the one field whose text differs from the BUDGET_EXHAUSTED refusal: here it says the action went through, and on a ceiling breach how far past the ceiling this row now stands, rather than telling you to set posture to warn when it already is. Branch on parameter, reason and blocked, never on this text. */
2823
2823
  message: string;
2824
2824
  };
2825
2825
  /**
@@ -6806,13 +6806,13 @@ interface operations {
6806
6806
  }[];
6807
6807
  /** @description Opaque cursor for the next page, or null at end-of-list. */
6808
6808
  cursor: string | null;
6809
- /** @description Present only when expand=public_identifier was asked for and this page held more people needing a profile lookup than one request performs. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
6809
+ /** @description Present only when expand=public_identifier was asked for and some people on this page went unresolved for a reason the payload cannot show: more of them needed a profile lookup than one request performs, the account is outside its activity window at this hour and enforces it, or the account's profile_views budget is at its configured ceiling and enforces that. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
6810
6810
  notices?: {
6811
6811
  /**
6812
- * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone.
6812
+ * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone. EXPANSION_WITHHELD_ACTIVITY_WINDOW: the profile lookups this page needed were refused because the account is outside its activity window at this hour and enforces it, so those people carry public_identifier null and their null does not mean they have no public profile either. Ask again inside the window, or widen the window on this account's safety policy. EXPANSION_WITHHELD_CEILING: the profile lookups this page needed were refused because the account's profile_views budget is at its configured ceiling and it enforces that, so those people carry public_identifier null and their null does not mean they have no public profile either. Raise the profile_views ceiling on this account's safety policy, or ask for a smaller page.
6813
6813
  * @enum {string}
6814
6814
  */
6815
- code: "EXPANSION_LIMIT_REACHED";
6815
+ code: "EXPANSION_LIMIT_REACHED" | "EXPANSION_WITHHELD_ACTIVITY_WINDOW" | "EXPANSION_WITHHELD_CEILING";
6816
6816
  /** @description One sentence explaining the condition and how to resolve it. */
6817
6817
  message: string;
6818
6818
  /** @description The request field the notice is about, here expand. */
@@ -6989,13 +6989,13 @@ interface operations {
6989
6989
  /** @description Message body (content pass-through, never stored). */
6990
6990
  text?: string | null;
6991
6991
  } | null;
6992
- /** @description Present only when expand=public_identifier was asked for and this page held more people needing a profile lookup than one request performs. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
6992
+ /** @description Present only when expand=public_identifier was asked for and some people on this page went unresolved for a reason the payload cannot show: more of them needed a profile lookup than one request performs, the account is outside its activity window at this hour and enforces it, or the account's profile_views budget is at its configured ceiling and enforces that. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
6993
6993
  notices?: {
6994
6994
  /**
6995
- * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone.
6995
+ * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone. EXPANSION_WITHHELD_ACTIVITY_WINDOW: the profile lookups this page needed were refused because the account is outside its activity window at this hour and enforces it, so those people carry public_identifier null and their null does not mean they have no public profile either. Ask again inside the window, or widen the window on this account's safety policy. EXPANSION_WITHHELD_CEILING: the profile lookups this page needed were refused because the account's profile_views budget is at its configured ceiling and it enforces that, so those people carry public_identifier null and their null does not mean they have no public profile either. Raise the profile_views ceiling on this account's safety policy, or ask for a smaller page.
6996
6996
  * @enum {string}
6997
6997
  */
6998
- code: "EXPANSION_LIMIT_REACHED";
6998
+ code: "EXPANSION_LIMIT_REACHED" | "EXPANSION_WITHHELD_ACTIVITY_WINDOW" | "EXPANSION_WITHHELD_CEILING";
6999
6999
  /** @description One sentence explaining the condition and how to resolve it. */
7000
7000
  message: string;
7001
7001
  /** @description The request field the notice is about, here expand. */
@@ -7165,13 +7165,13 @@ interface operations {
7165
7165
  }[];
7166
7166
  /** @description Opaque cursor for the next page, or null at end-of-list. */
7167
7167
  cursor: string | null;
7168
- /** @description Present only when expand=public_identifier was asked for and this page held more people needing a profile lookup than one request performs. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
7168
+ /** @description Present only when expand=public_identifier was asked for and some people on this page went unresolved for a reason the payload cannot show: more of them needed a profile lookup than one request performs, the account is outside its activity window at this hour and enforces it, or the account's profile_views budget is at its configured ceiling and enforces that. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
7169
7169
  notices?: {
7170
7170
  /**
7171
- * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone.
7171
+ * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone. EXPANSION_WITHHELD_ACTIVITY_WINDOW: the profile lookups this page needed were refused because the account is outside its activity window at this hour and enforces it, so those people carry public_identifier null and their null does not mean they have no public profile either. Ask again inside the window, or widen the window on this account's safety policy. EXPANSION_WITHHELD_CEILING: the profile lookups this page needed were refused because the account's profile_views budget is at its configured ceiling and it enforces that, so those people carry public_identifier null and their null does not mean they have no public profile either. Raise the profile_views ceiling on this account's safety policy, or ask for a smaller page.
7172
7172
  * @enum {string}
7173
7173
  */
7174
- code: "EXPANSION_LIMIT_REACHED";
7174
+ code: "EXPANSION_LIMIT_REACHED" | "EXPANSION_WITHHELD_ACTIVITY_WINDOW" | "EXPANSION_WITHHELD_CEILING";
7175
7175
  /** @description One sentence explaining the condition and how to resolve it. */
7176
7176
  message: string;
7177
7177
  /** @description The request field the notice is about, here expand. */
@@ -7508,13 +7508,13 @@ interface operations {
7508
7508
  sent_at: number;
7509
7509
  /** @description Message body (content pass-through, never stored). */
7510
7510
  text?: string | null;
7511
- /** @description Present only when expand=public_identifier was asked for and this page held more people needing a profile lookup than one request performs. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
7511
+ /** @description Present only when expand=public_identifier was asked for and some people on this page went unresolved for a reason the payload cannot show: more of them needed a profile lookup than one request performs, the account is outside its activity window at this hour and enforces it, or the account's profile_views budget is at its configured ceiling and enforces that. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
7512
7512
  notices?: {
7513
7513
  /**
7514
- * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone.
7514
+ * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone. EXPANSION_WITHHELD_ACTIVITY_WINDOW: the profile lookups this page needed were refused because the account is outside its activity window at this hour and enforces it, so those people carry public_identifier null and their null does not mean they have no public profile either. Ask again inside the window, or widen the window on this account's safety policy. EXPANSION_WITHHELD_CEILING: the profile lookups this page needed were refused because the account's profile_views budget is at its configured ceiling and it enforces that, so those people carry public_identifier null and their null does not mean they have no public profile either. Raise the profile_views ceiling on this account's safety policy, or ask for a smaller page.
7515
7515
  * @enum {string}
7516
7516
  */
7517
- code: "EXPANSION_LIMIT_REACHED";
7517
+ code: "EXPANSION_LIMIT_REACHED" | "EXPANSION_WITHHELD_ACTIVITY_WINDOW" | "EXPANSION_WITHHELD_CEILING";
7518
7518
  /** @description One sentence explaining the condition and how to resolve it. */
7519
7519
  message: string;
7520
7520
  /** @description The request field the notice is about, here expand. */
@@ -7714,13 +7714,13 @@ interface operations {
7714
7714
  * @enum {boolean}
7715
7715
  */
7716
7716
  filter_effective?: true;
7717
- /** @description Present only when expand=public_identifier was asked for and this page held more people needing a profile lookup than one request performs. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
7717
+ /** @description Present only when expand=public_identifier was asked for and some people on this page went unresolved for a reason the payload cannot show: more of them needed a profile lookup than one request performs, the account is outside its activity window at this hour and enforces it, or the account's profile_views budget is at its configured ceiling and enforces that. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
7718
7718
  notices?: {
7719
7719
  /**
7720
- * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone.
7720
+ * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone. EXPANSION_WITHHELD_ACTIVITY_WINDOW: the profile lookups this page needed were refused because the account is outside its activity window at this hour and enforces it, so those people carry public_identifier null and their null does not mean they have no public profile either. Ask again inside the window, or widen the window on this account's safety policy. EXPANSION_WITHHELD_CEILING: the profile lookups this page needed were refused because the account's profile_views budget is at its configured ceiling and it enforces that, so those people carry public_identifier null and their null does not mean they have no public profile either. Raise the profile_views ceiling on this account's safety policy, or ask for a smaller page.
7721
7721
  * @enum {string}
7722
7722
  */
7723
- code: "EXPANSION_LIMIT_REACHED";
7723
+ code: "EXPANSION_LIMIT_REACHED" | "EXPANSION_WITHHELD_ACTIVITY_WINDOW" | "EXPANSION_WITHHELD_CEILING";
7724
7724
  /** @description One sentence explaining the condition and how to resolve it. */
7725
7725
  message: string;
7726
7726
  /** @description The request field the notice is about, here expand. */
@@ -10361,13 +10361,13 @@ interface operations {
10361
10361
  }[];
10362
10362
  /** @description Next-page cursor; follow until items is empty (presence is not a has-more guarantee). */
10363
10363
  cursor?: string | null;
10364
- /** @description Present only when expand=public_identifier was asked for and this page held more people needing a profile lookup than one request performs. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
10364
+ /** @description Present only when expand=public_identifier was asked for and some people on this page went unresolved for a reason the payload cannot show: more of them needed a profile lookup than one request performs, the account is outside its activity window at this hour and enforces it, or the account's profile_views budget is at its configured ceiling and enforces that. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
10365
10365
  notices?: {
10366
10366
  /**
10367
- * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone.
10367
+ * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone. EXPANSION_WITHHELD_ACTIVITY_WINDOW: the profile lookups this page needed were refused because the account is outside its activity window at this hour and enforces it, so those people carry public_identifier null and their null does not mean they have no public profile either. Ask again inside the window, or widen the window on this account's safety policy. EXPANSION_WITHHELD_CEILING: the profile lookups this page needed were refused because the account's profile_views budget is at its configured ceiling and it enforces that, so those people carry public_identifier null and their null does not mean they have no public profile either. Raise the profile_views ceiling on this account's safety policy, or ask for a smaller page.
10368
10368
  * @enum {string}
10369
10369
  */
10370
- code: "EXPANSION_LIMIT_REACHED";
10370
+ code: "EXPANSION_LIMIT_REACHED" | "EXPANSION_WITHHELD_ACTIVITY_WINDOW" | "EXPANSION_WITHHELD_CEILING";
10371
10371
  /** @description One sentence explaining the condition and how to resolve it. */
10372
10372
  message: string;
10373
10373
  /** @description The request field the notice is about, here expand. */
@@ -10783,13 +10783,13 @@ interface operations {
10783
10783
  /** @description The vanity slug from the profile URL, for example jane-smith. Present only when the request asks for it with expand=public_identifier, and then always present, carrying the slug or null when the platform surfaces none for this person. */
10784
10784
  public_identifier?: string | null;
10785
10785
  };
10786
- /** @description Present only when expand=public_identifier was asked for and this page held more people needing a profile lookup than one request performs. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
10786
+ /** @description Present only when expand=public_identifier was asked for and some people on this page went unresolved for a reason the payload cannot show: more of them needed a profile lookup than one request performs, the account is outside its activity window at this hour and enforces it, or the account's profile_views budget is at its configured ceiling and enforces that. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
10787
10787
  notices?: {
10788
10788
  /**
10789
- * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone.
10789
+ * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone. EXPANSION_WITHHELD_ACTIVITY_WINDOW: the profile lookups this page needed were refused because the account is outside its activity window at this hour and enforces it, so those people carry public_identifier null and their null does not mean they have no public profile either. Ask again inside the window, or widen the window on this account's safety policy. EXPANSION_WITHHELD_CEILING: the profile lookups this page needed were refused because the account's profile_views budget is at its configured ceiling and it enforces that, so those people carry public_identifier null and their null does not mean they have no public profile either. Raise the profile_views ceiling on this account's safety policy, or ask for a smaller page.
10790
10790
  * @enum {string}
10791
10791
  */
10792
- code: "EXPANSION_LIMIT_REACHED";
10792
+ code: "EXPANSION_LIMIT_REACHED" | "EXPANSION_WITHHELD_ACTIVITY_WINDOW" | "EXPANSION_WITHHELD_CEILING";
10793
10793
  /** @description One sentence explaining the condition and how to resolve it. */
10794
10794
  message: string;
10795
10795
  /** @description The request field the notice is about, here expand. */
@@ -11143,13 +11143,13 @@ interface operations {
11143
11143
  }[];
11144
11144
  /** @description Next-page cursor; follow until items is empty. */
11145
11145
  cursor?: string | null;
11146
- /** @description Present only when expand=public_identifier was asked for and this page held more people needing a profile lookup than one request performs. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
11146
+ /** @description Present only when expand=public_identifier was asked for and some people on this page went unresolved for a reason the payload cannot show: more of them needed a profile lookup than one request performs, the account is outside its activity window at this hour and enforces it, or the account's profile_views budget is at its configured ceiling and enforces that. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
11147
11147
  notices?: {
11148
11148
  /**
11149
- * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone.
11149
+ * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone. EXPANSION_WITHHELD_ACTIVITY_WINDOW: the profile lookups this page needed were refused because the account is outside its activity window at this hour and enforces it, so those people carry public_identifier null and their null does not mean they have no public profile either. Ask again inside the window, or widen the window on this account's safety policy. EXPANSION_WITHHELD_CEILING: the profile lookups this page needed were refused because the account's profile_views budget is at its configured ceiling and it enforces that, so those people carry public_identifier null and their null does not mean they have no public profile either. Raise the profile_views ceiling on this account's safety policy, or ask for a smaller page.
11150
11150
  * @enum {string}
11151
11151
  */
11152
- code: "EXPANSION_LIMIT_REACHED";
11152
+ code: "EXPANSION_LIMIT_REACHED" | "EXPANSION_WITHHELD_ACTIVITY_WINDOW" | "EXPANSION_WITHHELD_CEILING";
11153
11153
  /** @description One sentence explaining the condition and how to resolve it. */
11154
11154
  message: string;
11155
11155
  /** @description The request field the notice is about, here expand. */
@@ -11519,13 +11519,13 @@ interface operations {
11519
11519
  [key: string]: unknown;
11520
11520
  };
11521
11521
  };
11522
- /** @description Present only when expand=public_identifier was asked for and this page held more people needing a profile lookup than one request performs. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
11522
+ /** @description Present only when expand=public_identifier was asked for and some people on this page went unresolved for a reason the payload cannot show: more of them needed a profile lookup than one request performs, the account is outside its activity window at this hour and enforces it, or the account's profile_views budget is at its configured ceiling and enforces that. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
11523
11523
  notices?: {
11524
11524
  /**
11525
- * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone.
11525
+ * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone. EXPANSION_WITHHELD_ACTIVITY_WINDOW: the profile lookups this page needed were refused because the account is outside its activity window at this hour and enforces it, so those people carry public_identifier null and their null does not mean they have no public profile either. Ask again inside the window, or widen the window on this account's safety policy. EXPANSION_WITHHELD_CEILING: the profile lookups this page needed were refused because the account's profile_views budget is at its configured ceiling and it enforces that, so those people carry public_identifier null and their null does not mean they have no public profile either. Raise the profile_views ceiling on this account's safety policy, or ask for a smaller page.
11526
11526
  * @enum {string}
11527
11527
  */
11528
- code: "EXPANSION_LIMIT_REACHED";
11528
+ code: "EXPANSION_LIMIT_REACHED" | "EXPANSION_WITHHELD_ACTIVITY_WINDOW" | "EXPANSION_WITHHELD_CEILING";
11529
11529
  /** @description One sentence explaining the condition and how to resolve it. */
11530
11530
  message: string;
11531
11531
  /** @description The request field the notice is about, here expand. */
@@ -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'). Terms of 3 or more characters are fast; a 1-2 character term is slower. */
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;
@@ -12725,13 +12725,13 @@ interface operations {
12725
12725
  }[];
12726
12726
  /** @description Next-page cursor. Follow until items is empty. */
12727
12727
  cursor?: string | null;
12728
- /** @description Present only when expand=public_identifier was asked for and this page held more people needing a profile lookup than one request performs. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
12728
+ /** @description Present only when expand=public_identifier was asked for and some people on this page went unresolved for a reason the payload cannot show: more of them needed a profile lookup than one request performs, the account is outside its activity window at this hour and enforces it, or the account's profile_views budget is at its configured ceiling and enforces that. Absent whenever there is nothing to report, so a response that resolved everyone carries no such key. Branch on each entry's code, never on its message. */
12729
12729
  notices?: {
12730
12730
  /**
12731
- * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone.
12731
+ * @description EXPANSION_LIMIT_REACHED: more people on this page needed a profile lookup than one request performs, so the ones past the budget carry public_identifier null without ever having been looked up. Their null therefore does not mean the person has no public profile. Ask for a smaller page to resolve everyone. EXPANSION_WITHHELD_ACTIVITY_WINDOW: the profile lookups this page needed were refused because the account is outside its activity window at this hour and enforces it, so those people carry public_identifier null and their null does not mean they have no public profile either. Ask again inside the window, or widen the window on this account's safety policy. EXPANSION_WITHHELD_CEILING: the profile lookups this page needed were refused because the account's profile_views budget is at its configured ceiling and it enforces that, so those people carry public_identifier null and their null does not mean they have no public profile either. Raise the profile_views ceiling on this account's safety policy, or ask for a smaller page.
12732
12732
  * @enum {string}
12733
12733
  */
12734
- code: "EXPANSION_LIMIT_REACHED";
12734
+ code: "EXPANSION_LIMIT_REACHED" | "EXPANSION_WITHHELD_ACTIVITY_WINDOW" | "EXPANSION_WITHHELD_CEILING";
12735
12735
  /** @description One sentence explaining the condition and how to resolve it. */
12736
12736
  message: string;
12737
12737
  /** @description The request field the notice is about, here expand. */
@@ -12985,7 +12985,7 @@ interface operations {
12985
12985
  "application/json": components["schemas"]["Error"];
12986
12986
  };
12987
12987
  };
12988
- /** @description A temporary upstream error occurred, or the upstream response could not be interpreted. Please try again. */
12988
+ /** @description A temporary upstream error occurred, or the upstream response could not be interpreted. Check `retry_likely_to_succeed`: a temporary error is worth retrying, a response that could not be interpreted is not, and carries `retry_hint: {"kind": "never"}`. */
12989
12989
  502: {
12990
12990
  headers: {
12991
12991
  [name: string]: unknown;
@@ -27956,6 +27956,10 @@ interface operations {
27956
27956
  ceiling: number | null;
27957
27957
  /** @description What this row is ACTUALLY held to right now: `ceiling` with the account's warm-up ramp applied. Compare `used` against THIS one, and `band` is computed against it too. While an account is new, thinly connected, dormant or recovering from a restriction the two differ, and on a five-day-old account they differ by a factor of about seven. Equal to `ceiling` once the ramp is over, and `null` wherever `ceiling` is null. The account's ramp, its factor and the triggers behind it are on GET /v1/{account_id}/safety-policy as `warm_up`. */
27958
27958
  effective_ceiling?: number | null;
27959
+ /** @description What a call through the matching ELEVATED interface is held to on this row: the `/v1/{account_id}/sales-navigator/...` and `/v1/{account_id}/recruiter/...` operations. Null when this row and limit profile have no such figure, which is every row on `basic` and `premium` and most rows everywhere. Everything else on this row (`ceiling`, `effective_ceiling`, `band` and `over_default`) is the STANDARD-interface figure, because one counter serves both interfaces and the standard side is the conservative one to band against. The consequence is worth reading: on a `sales_navigator` or `recruiter` account a row can report `band: "over"` with `posture: "enforce"` while a call through the elevated interface still succeeds; the refusal the band predicts is the one a standard call gets. */
27960
+ interface_ceiling?: number | null;
27961
+ /** @description `interface_ceiling` with the account's warm-up ramp applied, and null wherever `interface_ceiling` is null. Read THIS to know where an elevated-interface call stops, for the same reason `effective_ceiling` rather than `ceiling` answers that for a standard one. */
27962
+ effective_interface_ceiling?: number | null;
27959
27963
  /**
27960
27964
  * @description Where `used` sits against this row's own bands. `green` routine, `amber` at or past the routine band, `hard` at or past the warn-louder band, `over` at or past the ceiling. `over` is what `posture` acts on: `warn` reports it and lets the action through, `enforce` refuses. A row with no figures reports `green` at every value, because there is nothing to be past.
27961
27965
  * @enum {string}
@@ -29749,7 +29753,7 @@ interface operations {
29749
29753
  value: string;
29750
29754
  }[];
29751
29755
  /** @description Messaging events to subscribe to (default: [message.received]) */
29752
- events?: ("message.received" | "message.delivered" | "message.read" | "message.reaction" | "message.edited" | "message.deleted" | "chat.updated" | "chat.deleted")[];
29756
+ events?: ("message.received" | "message.read" | "message.reaction" | "message.edited" | "message.deleted" | "chat.updated" | "chat.deleted")[];
29753
29757
  /**
29754
29758
  * @description Field-remapping keys for the messaging delivery payload
29755
29759
  * @default []
@@ -30427,7 +30431,7 @@ interface operations {
30427
30431
  /** @description The account this policy governs. */
30428
30432
  account_id?: string;
30429
30433
  /**
30430
- * @description Which set of Curviate defaults every row below is resolved from. Each profile inherits the one before it and raises a few rows: `premium` adds a daily invitation band and open-profile InMail, `sales_navigator` raises profile views and search, `recruiter` raises profile views again. This is the platform product active on the account, not the Curviate seat entitlement. The two can disagree, and this is the one that governs the numbers. The elevated Sales Navigator and Recruiter figures apply only to calls made through the matching interface, the `/v1/{account_id}/sales-navigator/...` and `/v1/{account_id}/recruiter/...` operations. A standard-interface call still lives under the `basic` or `premium` figure for its row, and Curviate does not yet track that difference: on a non-`basic` profile the numbers here are the headroom of the elevated interface, not of every call, so read them as an upper bound rather than as your budget for a standard call.
30434
+ * @description Which set of Curviate defaults every row below is resolved from. Each profile inherits the one before it and raises a few rows: `premium` adds a daily invitation band and open-profile InMail, `sales_navigator` raises profile views and search, `recruiter` raises profile views again. This is the platform product active on the account, not the Curviate seat entitlement. The two can disagree, and this is the one that governs the numbers. The elevated Sales Navigator and Recruiter figures apply only to calls made through the matching interface, the `/v1/{account_id}/sales-navigator/...` and `/v1/{account_id}/recruiter/...` operations, and Curviate holds each call to the figure for the interface it goes through. The numbers here are therefore the ones a standard-interface call is held to, on every profile; a call through one of those operations resolves from the elevated set instead, and each row publishes that figure as `interface_ceiling`.
30431
30435
  * @enum {string}
30432
30436
  */
30433
30437
  limit_profile?: "basic" | "premium" | "sales_navigator" | "recruiter";
@@ -30510,7 +30514,7 @@ interface operations {
30510
30514
  /** @description IANA zone name the activity window is read in. Null disables the window entirely. */
30511
30515
  activity_window_timezone?: string | null;
30512
30516
  /**
30513
- * @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. Stored reads and inbound events are never subject to the window under either setting, at any hour.
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.
30514
30518
  * @enum {string}
30515
30519
  */
30516
30520
  activity_window_applies_to?: "writes" | "all";
@@ -30534,7 +30538,11 @@ interface operations {
30534
30538
  source_class?: "substrate" | "linkedin_official" | "practitioner" | "inferred" | "unseeded";
30535
30539
  /** @description What this row is ACTUALLY held to right now: `ceiling` with the account's warm-up ramp applied. Read this one, not `ceiling`, to know where the next call will be stopped. On an account in warm-up the two differ, and on a five-day-old account they differ by a factor of about seven. Null when the row has no ceiling to ramp. `warm_up_state` and `warm_up_factor` beside it are the values ACTIVE on this row, not the seeded ones. */
30536
30540
  effective_ceiling?: number | null;
30537
- /** @description Empty when nothing on this row is above default. */
30541
+ /** @description What a call through the matching ELEVATED interface is held to on this row: the `/v1/{account_id}/sales-navigator/...` and `/v1/{account_id}/recruiter/...` operations. Null when this row and limit profile have no such figure, which is every row on `basic` and `premium` and most rows everywhere. Everything else on this row (`ceiling`, `effective_ceiling`, `band` and `over_default`) is the STANDARD-interface figure, because one counter serves both interfaces and the standard side is the conservative one to band against. The consequence is worth reading: on a `sales_navigator` or `recruiter` account a row can report `band: "over"` with `posture: "enforce"` while a call through the elevated interface still succeeds; the refusal the band predicts is the one a standard call gets. */
30542
+ interface_ceiling?: number | null;
30543
+ /** @description `interface_ceiling` with the account's warm-up ramp applied, and null wherever `interface_ceiling` is null. Read THIS to know where an elevated-interface call stops, for the same reason `effective_ceiling` rather than `ceiling` answers that for a standard one. */
30544
+ effective_interface_ceiling?: number | null;
30545
+ /** @description Empty when nothing on this row is above default. Computed against the STANDARD-interface default, like `band` and for the same reason. */
30538
30546
  over_default?: {
30539
30547
  /**
30540
30548
  * @description The field whose configured value is above default.
@@ -30593,7 +30601,7 @@ interface operations {
30593
30601
  content: {
30594
30602
  "application/json": {
30595
30603
  /**
30596
- * @description Which set of Curviate defaults this account's rows resolve from: `basic`, `premium`, `sales_navigator` or `recruiter`. Each inherits the one before it and raises a few rows. This is the platform product active on the account, NOT the Curviate seat entitlement, and the two can disagree: a lapsed subscription leaves the seat untouched. Automatic detection at connect is not built yet, so setting this is currently the only way an account leaves `basic`; set it back to `basic` to undo. The change is recorded in the ledger and it moves the defaults under every row at once, so any row you have configured explicitly keeps your value. The elevated Sales Navigator and Recruiter figures apply only to calls made through the matching interface, the `/v1/{account_id}/sales-navigator/...` and `/v1/{account_id}/recruiter/...` operations. A standard-interface call still lives under the `basic` or `premium` figure for its row, and Curviate does not yet track that difference: on a non-`basic` profile the numbers here are the headroom of the elevated interface, not of every call, so read them as an upper bound rather than as your budget for a standard call.
30604
+ * @description Which set of Curviate defaults this account's rows resolve from: `basic`, `premium`, `sales_navigator` or `recruiter`. Each inherits the one before it and raises a few rows. This is the platform product active on the account, NOT the Curviate seat entitlement, and the two can disagree: a lapsed subscription leaves the seat untouched. Curviate detects it from the platform when the account connects and re-detects it on every reconnect; setting it here is an operator override of that result and holds until the next connect. Set it back to `basic` to undo. The change is recorded in the ledger and it moves the defaults under every row at once, so any row you have configured explicitly keeps your value. The elevated Sales Navigator and Recruiter figures apply only to calls made through the matching interface, the `/v1/{account_id}/sales-navigator/...` and `/v1/{account_id}/recruiter/...` operations, and Curviate holds each call to the figure for the interface it goes through. The numbers here are therefore the ones a standard-interface call is held to, on every profile; a call through one of those operations resolves from the elevated set instead, and each row publishes that figure as `interface_ceiling`.
30597
30605
  * @enum {string}
30598
30606
  */
30599
30607
  limit_profile?: "basic" | "premium" | "sales_navigator" | "recruiter";
@@ -30643,7 +30651,7 @@ interface operations {
30643
30651
  /** @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. */
30644
30652
  activity_window_timezone?: string | null;
30645
30653
  /**
30646
- * @description What the activity window governs. `writes` (the default) covers live writes to LinkedIn; `all` widens it to live reads that Curviate cannot serve from its store; a read it may serve from the store (a profile by key, for one) stays exempt. Stored reads and inbound events are never subject to the window under either setting, at any hour.
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.
30647
30655
  * @enum {string|null}
30648
30656
  */
30649
30657
  activity_window_applies_to?: "writes" | "all" | null;
@@ -30667,6 +30675,10 @@ interface operations {
30667
30675
  source_class?: "substrate" | "linkedin_official" | "practitioner" | "inferred" | "unseeded" | null;
30668
30676
  /** @description READ-ONLY. `ceiling` with the account's warm-up ramp applied, which is what this row is actually held to. Sent back on a write it is accepted and ignored, so the whole document round-trips; it is never stored and never ledgered. */
30669
30677
  effective_ceiling?: unknown;
30678
+ /** @description READ-ONLY. What a call through the matching elevated interface (`/v1/{account_id}/sales-navigator/...`, `/v1/{account_id}/recruiter/...`) is held to on this row, or null when this row and limit profile have no such figure. `ceiling`, `effective_ceiling`, `band` and `over_default` are all the STANDARD-interface figure, so on a `sales_navigator` or `recruiter` account a row can report `over` while a call through the elevated interface still succeeds. Sent back on a write it is accepted and ignored, so the whole document round-trips; it is never stored and never ledgered. */
30679
+ interface_ceiling?: unknown;
30680
+ /** @description READ-ONLY. `interface_ceiling` with the account's warm-up ramp applied. Read THIS to know where an elevated-interface call stops, for the same reason `effective_ceiling` and not `ceiling` answers that for a standard one. Sent back on a write it is accepted and ignored, so the whole document round-trips; it is never stored and never ledgered. */
30681
+ effective_interface_ceiling?: unknown;
30670
30682
  /** @description READ-ONLY. Which scope supplied this row's effective `posture`. Sent back on a write it is accepted and ignored, so the whole document round-trips; it is never stored and never ledgered. */
30671
30683
  posture_source?: unknown;
30672
30684
  /** @description READ-ONLY. The fields on this row configured above the Curviate default. Sent back on a write it is accepted and ignored, so the whole document round-trips; it is never stored and never ledgered. */
@@ -30682,6 +30694,8 @@ interface operations {
30682
30694
  posture_source?: unknown;
30683
30695
  /** @description READ-ONLY. The account's DERIVED warm-up ramp, recomputed on every read. Sent back on a write it is accepted and ignored, so the whole document round-trips; it is never stored and never ledgered. */
30684
30696
  warm_up?: unknown;
30697
+ /** @description NOT ACCEPTED. Send its settable subfields instead: the top-level `timezone`, and per row `activity_window_start`, `activity_window_end`, `activity_window_timezone`, `activity_window_applies_to`. */
30698
+ activity_window?: unknown;
30685
30699
  };
30686
30700
  };
30687
30701
  };
@@ -30703,7 +30717,7 @@ interface operations {
30703
30717
  /** @description The account this policy governs. */
30704
30718
  account_id?: string;
30705
30719
  /**
30706
- * @description Which set of Curviate defaults every row below is resolved from. Each profile inherits the one before it and raises a few rows: `premium` adds a daily invitation band and open-profile InMail, `sales_navigator` raises profile views and search, `recruiter` raises profile views again. This is the platform product active on the account, not the Curviate seat entitlement. The two can disagree, and this is the one that governs the numbers. The elevated Sales Navigator and Recruiter figures apply only to calls made through the matching interface, the `/v1/{account_id}/sales-navigator/...` and `/v1/{account_id}/recruiter/...` operations. A standard-interface call still lives under the `basic` or `premium` figure for its row, and Curviate does not yet track that difference: on a non-`basic` profile the numbers here are the headroom of the elevated interface, not of every call, so read them as an upper bound rather than as your budget for a standard call.
30720
+ * @description Which set of Curviate defaults every row below is resolved from. Each profile inherits the one before it and raises a few rows: `premium` adds a daily invitation band and open-profile InMail, `sales_navigator` raises profile views and search, `recruiter` raises profile views again. This is the platform product active on the account, not the Curviate seat entitlement. The two can disagree, and this is the one that governs the numbers. The elevated Sales Navigator and Recruiter figures apply only to calls made through the matching interface, the `/v1/{account_id}/sales-navigator/...` and `/v1/{account_id}/recruiter/...` operations, and Curviate holds each call to the figure for the interface it goes through. The numbers here are therefore the ones a standard-interface call is held to, on every profile; a call through one of those operations resolves from the elevated set instead, and each row publishes that figure as `interface_ceiling`.
30707
30721
  * @enum {string}
30708
30722
  */
30709
30723
  limit_profile?: "basic" | "premium" | "sales_navigator" | "recruiter";
@@ -30786,7 +30800,7 @@ interface operations {
30786
30800
  /** @description IANA zone name the activity window is read in. Null disables the window entirely. */
30787
30801
  activity_window_timezone?: string | null;
30788
30802
  /**
30789
- * @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. Stored reads and inbound events are never subject to the window under either setting, at any hour.
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.
30790
30804
  * @enum {string}
30791
30805
  */
30792
30806
  activity_window_applies_to?: "writes" | "all";
@@ -30810,7 +30824,11 @@ interface operations {
30810
30824
  source_class?: "substrate" | "linkedin_official" | "practitioner" | "inferred" | "unseeded";
30811
30825
  /** @description What this row is ACTUALLY held to right now: `ceiling` with the account's warm-up ramp applied. Read this one, not `ceiling`, to know where the next call will be stopped. On an account in warm-up the two differ, and on a five-day-old account they differ by a factor of about seven. Null when the row has no ceiling to ramp. `warm_up_state` and `warm_up_factor` beside it are the values ACTIVE on this row, not the seeded ones. */
30812
30826
  effective_ceiling?: number | null;
30813
- /** @description Empty when nothing on this row is above default. */
30827
+ /** @description What a call through the matching ELEVATED interface is held to on this row: the `/v1/{account_id}/sales-navigator/...` and `/v1/{account_id}/recruiter/...` operations. Null when this row and limit profile have no such figure, which is every row on `basic` and `premium` and most rows everywhere. Everything else on this row (`ceiling`, `effective_ceiling`, `band` and `over_default`) is the STANDARD-interface figure, because one counter serves both interfaces and the standard side is the conservative one to band against. The consequence is worth reading: on a `sales_navigator` or `recruiter` account a row can report `band: "over"` with `posture: "enforce"` while a call through the elevated interface still succeeds; the refusal the band predicts is the one a standard call gets. */
30828
+ interface_ceiling?: number | null;
30829
+ /** @description `interface_ceiling` with the account's warm-up ramp applied, and null wherever `interface_ceiling` is null. Read THIS to know where an elevated-interface call stops, for the same reason `effective_ceiling` rather than `ceiling` answers that for a standard one. */
30830
+ effective_interface_ceiling?: number | null;
30831
+ /** @description Empty when nothing on this row is above default. Computed against the STANDARD-interface default, like `band` and for the same reason. */
30814
30832
  over_default?: {
30815
30833
  /**
30816
30834
  * @description The field whose configured value is above default.
@@ -30920,15 +30938,15 @@ interface operations {
30920
30938
  /** @description The event's id. Also the value encoded in the next page's cursor. */
30921
30939
  id: string;
30922
30940
  /**
30923
- * @description The budget row that breached. It is not always a row the call itself spends: an invitation refused because the outstanding backlog is at its ceiling reports `pending_invites`, which is the thing that breached.
30941
+ * @description The budget row that breached. It is not always a row the call itself spends: an invitation refused because the outstanding backlog is at its ceiling reports `pending_invites`, which is the thing that breached. `*` means the event was not about a row at all: the activity window closing on an action that spends no budget of its own, such as editing a message or a Recruiter admin action. The `budget_row` filter accepts real row names only, so page without it to see those.
30924
30942
  * @enum {string}
30925
30943
  */
30926
- 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";
30944
+ 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" | "*";
30927
30945
  /**
30928
- * @description Why it was flagged. `budget_exhausted`: the account reached the ceiling configured for that row, which you can raise on the safety policy. `rate_limited`: the platform itself refused this account on that row recently and Curviate is holding the row until the pause expires, which no configuration change lifts.
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 no configuration change lifts.
30929
30947
  * @enum {string}
30930
30948
  */
30931
- reason: "budget_exhausted" | "rate_limited";
30949
+ reason: "budget_exhausted" | "activity_window" | "rate_limited";
30932
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. */
30933
30951
  blocked: boolean;
30934
30952
  /** @description The operation the caller was running when it breached. */
@@ -31232,6 +31250,7 @@ type ChatListQuery = NonNullable<paths["/v1/{account_id}/chats"]["get"]["paramet
31232
31250
  type StartChatBody = paths["/v1/{account_id}/chats"]["post"]["requestBody"]["content"]["application/json"];
31233
31251
  type StartChatResult = paths["/v1/{account_id}/chats"]["post"]["responses"]["201"]["content"]["application/json"];
31234
31252
  type ChatDetail = paths["/v1/{account_id}/chats/{chat_id}"]["get"]["responses"]["200"]["content"]["application/json"];
31253
+ type ChatGetQuery = NonNullable<paths["/v1/{account_id}/chats/{chat_id}"]["get"]["parameters"]["query"]>;
31235
31254
  type MarkChatReadBody = paths["/v1/{account_id}/chats/{chat_id}"]["patch"]["requestBody"]["content"]["application/json"];
31236
31255
  type MarkChatReadResult = paths["/v1/{account_id}/chats/{chat_id}"]["patch"]["responses"]["200"]["content"]["application/json"];
31237
31256
  type MessageListPage = paths["/v1/{account_id}/chats/{chat_id}/messages"]["get"]["responses"]["200"]["content"]["application/json"];
@@ -31263,8 +31282,15 @@ declare class MessagingResource {
31263
31282
  * `COMPANY_` chat id from `inboxes.listChats()`.
31264
31283
  */
31265
31284
  startChat(body: StartChatBody): Promise<StartChatResult>;
31266
- /** Get details of a single chat. `GET /v1/{account_id}/chats/{chat_id}` */
31267
- getChat(chatId: string): Promise<ChatDetail>;
31285
+ /**
31286
+ * Get details of a single chat. `GET /v1/{account_id}/chats/{chat_id}`
31287
+ *
31288
+ * A store-servable read: `{ mode, max_age }` says how willing it is to reach
31289
+ * LinkedIn, and the response's `source` says which way the answer came. See
31290
+ * "Retrieval modes" in the README for the four modes and what `max_age`
31291
+ * overrides.
31292
+ */
31293
+ getChat(chatId: string, params?: ChatGetQuery): Promise<ChatDetail>;
31268
31294
  /**
31269
31295
  * Mark a chat read or unread. `PATCH /v1/{account_id}/chats/{chat_id}`
31270
31296
  * Body: `{read}`.
@@ -33077,7 +33103,7 @@ declare class Curviate {
33077
33103
  * The taxonomy is additive-only: new codes may be appended, existing ones are
33078
33104
  * never removed or renamed.
33079
33105
  */
33080
- declare const ERROR_CODES: readonly ["UNAUTHORIZED", "INVALID_REQUEST", "UNSUPPORTED_MEDIA_TYPE", "PAYLOAD_TOO_LARGE", "ACCOUNT_NOT_FOUND", "ACCOUNT_RESTRICTED", "ACCOUNT_ALREADY_LINKED", "RESOURCE_NOT_FOUND", "RESOURCE_ACCESS_RESTRICTED", "FILTER_CANDIDATES_REQUIRED", "TIER_NOT_ACTIVE", "LINKEDIN_FEATURE_NOT_SUBSCRIBED", "RATE_LIMIT_ACCOUNT", "RATE_LIMIT_TENANT", "PLATFORM_RATE_LIMIT", "RATE_LIMITED", "BUDGET_EXHAUSTED", "PLATFORM_ERROR", "PLATFORM_NOT_IMPLEMENTED", "LINKEDIN_OPERATION_NOT_SUPPORTED", "CHECKPOINT_NOT_FOUND", "CHECKPOINT_EXPIRED", "CHECKPOINT_INVALID_CODE", "CHECKPOINT_MAX_ATTEMPTS", "CHECKPOINT_ALREADY_RESOLVED", "CHECKPOINT_UNSUPPORTED", "CONNECTION_IN_PROGRESS", "PREMIUM_CONFLICT", "REAUTH_REQUIRED", "LINKEDIN_AUTH_FAILED", "LINKEDIN_SESSION_EVICTED", "LINKEDIN_RATE_LIMITED", "LINKEDIN_COOKIE_INVALID", "LINKEDIN_SERVICE_UNAVAILABLE", "MESSAGE_WINDOW_EXPIRED", "RECIPIENT_UNREACHABLE", "CONNECTION_REQUEST_CONFLICT", "PAYMENT_REQUIRED", "PAYMENT_FAILED", "SUBSCRIPTION_BUSY", "SUBSCRIPTION_NOT_FOUND", "SEAT_NOT_FOUND", "SEAT_CANCELLED", "INTERNAL"];
33106
+ declare const ERROR_CODES: readonly ["UNAUTHORIZED", "INVALID_REQUEST", "UNSUPPORTED_MEDIA_TYPE", "PAYLOAD_TOO_LARGE", "ACCOUNT_NOT_FOUND", "ACCOUNT_RESTRICTED", "ACCOUNT_ALREADY_LINKED", "RESOURCE_NOT_FOUND", "NOT_STORED", "RESOURCE_ACCESS_RESTRICTED", "FILTER_CANDIDATES_REQUIRED", "TIER_NOT_ACTIVE", "LINKEDIN_FEATURE_NOT_SUBSCRIBED", "RATE_LIMIT_ACCOUNT", "RATE_LIMIT_TENANT", "PLATFORM_RATE_LIMIT", "RATE_LIMITED", "BUDGET_EXHAUSTED", "PLATFORM_ERROR", "PLATFORM_NOT_IMPLEMENTED", "LINKEDIN_OPERATION_NOT_SUPPORTED", "CHECKPOINT_NOT_FOUND", "CHECKPOINT_EXPIRED", "CHECKPOINT_INVALID_CODE", "CHECKPOINT_MAX_ATTEMPTS", "CHECKPOINT_ALREADY_RESOLVED", "CHECKPOINT_UNSUPPORTED", "CONNECTION_IN_PROGRESS", "PREMIUM_CONFLICT", "REAUTH_REQUIRED", "LINKEDIN_AUTH_FAILED", "LINKEDIN_SESSION_EVICTED", "LINKEDIN_RATE_LIMITED", "LINKEDIN_COOKIE_INVALID", "LINKEDIN_SERVICE_UNAVAILABLE", "MESSAGE_WINDOW_EXPIRED", "RECIPIENT_UNREACHABLE", "CONNECTION_REQUEST_CONFLICT", "PAYMENT_REQUIRED", "PAYMENT_FAILED", "SUBSCRIPTION_BUSY", "SUBSCRIPTION_NOT_FOUND", "SEAT_NOT_FOUND", "SEAT_CANCELLED", "INTERNAL"];
33081
33107
  /**
33082
33108
  * The complete set of error codes observable by API callers.
33083
33109
  *
@@ -33414,6 +33440,10 @@ interface CurviateEventEnvelope {
33414
33440
  * the generated create-events enum (see `test/webhooks.constructEvent.test.ts`);
33415
33441
  * it must never drift from the served catalogue again.
33416
33442
  *
33443
+ * > Removed in 0.27.0 (BREAKING): `message.delivered`. The platform never
33444
+ * > emitted it, so no `event.event === 'message.delivered'` branch has ever
33445
+ * > run. The read-path replacement is `is_delivered` on the message resource.
33446
+ *
33417
33447
  * @example
33418
33448
  * const event = await constructEvent(rawBody, header, secret);
33419
33449
  * if (event.event === 'message.received') {
@@ -33423,9 +33453,6 @@ interface CurviateEventEnvelope {
33423
33453
  type CurviateEvent = CurviateEventEnvelope & ({
33424
33454
  event: "message.received";
33425
33455
  data: MessagePayload;
33426
- } | {
33427
- event: "message.delivered";
33428
- data: MessagePayload;
33429
33456
  } | {
33430
33457
  event: "message.read";
33431
33458
  data: MessagePayload;
package/dist/index.js CHANGED
@@ -12,6 +12,14 @@ var ERROR_CODES = [
12
12
  // linking again. Not retryable.
13
13
  "ACCOUNT_ALREADY_LINKED",
14
14
  "RESOURCE_NOT_FOUND",
15
+ // A read found nothing in Curviate's store and its mode may not fetch, so it
16
+ // refused rather than reaching LinkedIn. 422, and NOT RESOURCE_NOT_FOUND: the
17
+ // resource may be perfectly real, so the fix is another mode, not another id.
18
+ // Absent from RETRYABLE_CODES on purpose, nothing about the answer changes
19
+ // until the caller picks one.
20
+ //
21
+ // `cache_only` is the mode that raises it; re-read with `refill` or `auto`.
22
+ "NOT_STORED",
15
23
  "RESOURCE_ACCESS_RESTRICTED",
16
24
  // Search filter resolution: a plain-string filter value matched several
17
25
  // LinkedIn taxonomy options and one has to be picked (422). The body carries
@@ -653,11 +661,19 @@ var MessagingResource = class {
653
661
  body
654
662
  });
655
663
  }
656
- /** Get details of a single chat. `GET /v1/{account_id}/chats/{chat_id}` */
657
- getChat(chatId) {
664
+ /**
665
+ * Get details of a single chat. `GET /v1/{account_id}/chats/{chat_id}`
666
+ *
667
+ * A store-servable read: `{ mode, max_age }` says how willing it is to reach
668
+ * LinkedIn, and the response's `source` says which way the answer came. See
669
+ * "Retrieval modes" in the README for the four modes and what `max_age`
670
+ * overrides.
671
+ */
672
+ getChat(chatId, params) {
658
673
  return this.ctx.request({
659
674
  method: "GET",
660
- path: apiPath`/v1/{account_id}/chats/${chatId}`
675
+ path: apiPath`/v1/{account_id}/chats/${chatId}`,
676
+ ...params ? { query: params } : {}
661
677
  });
662
678
  }
663
679
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curviate/sdk",
3
- "version": "0.25.0",
3
+ "version": "0.27.0",
4
4
  "private": false,
5
5
  "description": "TypeScript SDK for the Curviate API.",
6
6
  "license": "MIT",