@curviate/sdk 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,28 @@ Versioning: semantic — minor for additive changes, patch for bug fixes; no sta
7
7
 
8
8
  ---
9
9
 
10
+ ## [0.10.0] — 2026-07-03
11
+
12
+ ### Added
13
+
14
+ - **New `jobs` namespace.** `jobs.get(jobIdOrUrl)` retrieves one public LinkedIn job posting's full detail — title, company, location, description, applicant count, and more. Accepts either a bare numeric job id (e.g. `"4428113858"`) or a full job URL (`"https://www.linkedin.com/jobs/view/4428113858"`) — the SDK extracts the numeric id client-side, so both forms issue the identical request. Passing a value with no extractable numeric id throws `CurviateError({ code: "INVALID_REQUEST" })` synchronously, before any network call. Type: `JobPosting`.
15
+ - `recruiter.getJob(jobIdOrUrl)` — the Recruiter-lens sibling, retrieving any public job posting (not only the operator's own postings). Accepts the same bare-id-or-URL forms as `jobs.get()` and returns the identical `JobPosting` type (no separate response shape to learn). Extends the Recruiter surface to 18 methods.
16
+
17
+ ## [0.9.0] — 2026-07-03
18
+
19
+ ### Added
20
+
21
+ - **Account enrichment fields.** `accounts.list()` items and `accounts.get()` now carry six cached account-detail fields, populated by an async background enrichment on every successful account activation: `username`, `premium_id`, `public_identifier`, `substrate_created_at` (ISO-8601 UTC), `signatures` (`{title, content}[]`), and `groups` (`string[]`). All six are `null`/`[]` until the account's first enrichment pass completes — never `undefined`, never a missing key. Types: `AccountListPage`, `AccountDetail`.
22
+ - `accounts.get()` gains `seat_id` (`string | null`) — the seat the account occupies, `null` for an admin seatless account. Previously only `accounts.list()` items carried this field.
23
+
24
+ ### Changed
25
+
26
+ - `connected_at` (on both `accounts.list()` items and `accounts.get()`) and `last_checked_at` (`accounts.get()`) now consistently emit ISO-8601 UTC (`…Z`) timestamps — a prior docs-vs-runtime drift meant these could reach callers in raw Postgres wire format. No type change (already typed as `string`/`string | null`); this is a runtime-correctness fix reflected in the regenerated example values.
27
+ - Regenerated types from the current API surface. No resource method signatures changed — purely additive response fields.
28
+ - `quotas[]` (on `accounts.get()`) is now documented as advisory usage-safety recommendations: daily families never cause a rejected request; only `account.per_minute` is a binding limit enforced with HTTP 429. `recommended_throttle_hint` semantics documented per level (`none` / `slow_down` / `backoff` are advisory; `stop` is reserved for the binding per-minute limit). JSDoc-only — no type shape change.
29
+
30
+ ---
31
+
10
32
  ## [0.8.0] — 2026-07-02
11
33
 
12
34
  ### Added
package/dist/index.d.ts CHANGED
@@ -164,8 +164,23 @@ interface paths {
164
164
  headline?: string | null;
165
165
  /** @description The seat this account occupies. */
166
166
  seat_id?: string | null;
167
- /** @description ISO-8601 connection timestamp. */
168
- connected_at?: string;
167
+ /** @description ISO-8601 UTC connection timestamp. */
168
+ connected_at?: string | null;
169
+ /** @description Cached account username. Null until enriched. */
170
+ username?: string | null;
171
+ /** @description Cached premium-membership id. Null until enriched, or for non-premium accounts. */
172
+ premium_id?: string | null;
173
+ /** @description Cached public profile identifier. Null until enriched. */
174
+ public_identifier?: string | null;
175
+ /** @description ISO-8601 UTC creation timestamp of the underlying LinkedIn account — distinct from connected_at. Null until enriched. */
176
+ substrate_created_at?: string | null;
177
+ /** @description Cached signature blocks (title + content) for the account. Empty until enriched. */
178
+ signatures?: {
179
+ title?: string;
180
+ content?: string;
181
+ }[];
182
+ /** @description Cached group names the account belongs to. Empty until enriched. */
183
+ groups?: string[];
169
184
  }[];
170
185
  /** @description Next-page cursor; null on the last page. */
171
186
  cursor?: string | null;
@@ -508,9 +523,28 @@ interface paths {
508
523
  auth_method?: string;
509
524
  full_name?: string | null;
510
525
  headline?: string | null;
526
+ /** @description ISO-8601 UTC connection timestamp. */
511
527
  connected_at?: string | null;
528
+ /** @description ISO-8601 UTC time the account state was last checked. */
512
529
  last_checked_at?: string;
513
- /** @description Per-account quota view one entry per tracked family (messages.daily, connection_requests.daily, profile_views.daily, inmail.daily, account.per_minute). */
530
+ /** @description The seat this account occupies (null for an admin seatless account). */
531
+ seat_id?: string | null;
532
+ /** @description Cached account username. Null until enriched. */
533
+ username?: string | null;
534
+ /** @description Cached premium-membership id. Null until enriched, or for non-premium accounts. */
535
+ premium_id?: string | null;
536
+ /** @description Cached public profile identifier. Null until enriched. */
537
+ public_identifier?: string | null;
538
+ /** @description ISO-8601 UTC creation timestamp of the underlying LinkedIn account — distinct from connected_at. Null until enriched. */
539
+ substrate_created_at?: string | null;
540
+ /** @description Cached signature blocks (title + content) for the account. Empty until enriched. */
541
+ signatures?: {
542
+ title?: string;
543
+ content?: string;
544
+ }[];
545
+ /** @description Cached group names the account belongs to. Empty until enriched. */
546
+ groups?: string[];
547
+ /** @description Usage-safety recommendations for this account — one entry per tracked family (messages.daily, connection_requests.daily, profile_views.daily, inmail.daily, profile.endorse, account.per_minute). These are advisory only: Curviate never rejects a request because a daily recommendation is exceeded; only account.per_minute is a binding limit enforced with HTTP 429. */
514
548
  quotas?: {
515
549
  /** @description Quota family (e.g. messages.daily, account.per_minute). */
516
550
  quota_name?: string;
@@ -521,7 +555,7 @@ interface paths {
521
555
  /** @description ISO-8601 UTC time the current window resets. */
522
556
  reset_time?: string;
523
557
  /**
524
- * @description Pacing hint.
558
+ * @description Pacing recommendation for this family, advisory only. `none` (under 80% consumed), `slow_down` (80-99% consumed), and `backoff` (100%+ consumed) never block a request. `stop` is reserved exclusively for `account.per_minute` — the sole binding limit, whose breach is enforced with HTTP 429.
525
559
  * @enum {string}
526
560
  */
527
561
  recommended_throttle_hint?: "none" | "slow_down" | "backoff" | "stop";
@@ -2486,6 +2520,176 @@ interface paths {
2486
2520
  patch?: never;
2487
2521
  trace?: never;
2488
2522
  };
2523
+ "/v1/jobs/{job_id}": {
2524
+ parameters: {
2525
+ query?: never;
2526
+ header?: never;
2527
+ path?: never;
2528
+ cookie?: never;
2529
+ };
2530
+ /**
2531
+ * Get job posting
2532
+ * @description Returns one public LinkedIn job posting's full detail — title, company, location, description, and applicant count.
2533
+ */
2534
+ get: {
2535
+ parameters: {
2536
+ query: {
2537
+ /** @description The connected LinkedIn account to retrieve the job posting on behalf of. */
2538
+ account_id: string;
2539
+ };
2540
+ header?: never;
2541
+ path: {
2542
+ /** @description The numeric id of the job posting, e.g. 4428113858. This is the number in a LinkedIn job URL (https://www.linkedin.com/jobs/view/4428113858) and the job_urn value in a POST /v1/search/jobs result. Pass the number only — a full URL is not accepted by the API (the SDK and CLI extract the id from a URL for you). */
2543
+ job_id: string;
2544
+ };
2545
+ cookie?: never;
2546
+ };
2547
+ requestBody?: never;
2548
+ responses: {
2549
+ /** @description The job posting's full detail. Content fields (title, description) are returned verbatim and are never stored. */
2550
+ 200: {
2551
+ headers: {
2552
+ "RateLimit-Policy": components["headers"]["RateLimit-Policy"];
2553
+ RateLimit: components["headers"]["RateLimit"];
2554
+ [name: string]: unknown;
2555
+ };
2556
+ content: {
2557
+ "application/json": {
2558
+ /**
2559
+ * @description Response type discriminator.
2560
+ * @enum {string}
2561
+ */
2562
+ object: "job_posting";
2563
+ /** @description The job posting's numeric identifier. */
2564
+ id: string;
2565
+ /** @description Job title (content pass-through — never stored). */
2566
+ title: string;
2567
+ /** @description Hiring company's display name. */
2568
+ company: string;
2569
+ /** @description The hiring company's id — pass it to GET /v1/profiles/companies/{company_id}. */
2570
+ company_id: string;
2571
+ /** @description Posting lifecycle state (e.g. active). */
2572
+ state: string;
2573
+ /** @description Job location, or null when not set. */
2574
+ location: string | null;
2575
+ /** @description Posting cost, in the currency the account bills in. */
2576
+ cost: number;
2577
+ /** @description Number of applicants so far. */
2578
+ applicants_counter: number;
2579
+ /** @description Full job description text (content pass-through — never stored). */
2580
+ description: string;
2581
+ /** @description ISO-8601 UTC timestamp the posting was created, or null when not set. */
2582
+ created_at: string | null;
2583
+ /** @description ISO-8601 UTC timestamp the posting was published, or null when not set. */
2584
+ published_at: string | null;
2585
+ /** @description Hiring team members associated with this posting, when the posting exposes any. */
2586
+ hiring_team: unknown[];
2587
+ };
2588
+ };
2589
+ };
2590
+ /** @description Missing or empty account_id. */
2591
+ 400: {
2592
+ headers: {
2593
+ [name: string]: unknown;
2594
+ };
2595
+ content: {
2596
+ "application/json": components["schemas"]["Error"];
2597
+ };
2598
+ };
2599
+ /** @description Missing or invalid API key. */
2600
+ 401: {
2601
+ headers: {
2602
+ [name: string]: unknown;
2603
+ };
2604
+ content: {
2605
+ "application/json": components["schemas"]["Error"];
2606
+ };
2607
+ };
2608
+ /** @description The account does not have the required Core seat. */
2609
+ 403: {
2610
+ headers: {
2611
+ [name: string]: unknown;
2612
+ };
2613
+ content: {
2614
+ "application/json": components["schemas"]["Error"];
2615
+ };
2616
+ };
2617
+ /** @description The account_id does not belong to this tenant, or the job posting was not found. */
2618
+ 404: {
2619
+ headers: {
2620
+ [name: string]: unknown;
2621
+ };
2622
+ content: {
2623
+ "application/json": components["schemas"]["Error"];
2624
+ };
2625
+ };
2626
+ /** @description The account is restricted and cannot be queried. */
2627
+ 422: {
2628
+ headers: {
2629
+ [name: string]: unknown;
2630
+ };
2631
+ content: {
2632
+ "application/json": components["schemas"]["Error"];
2633
+ };
2634
+ };
2635
+ /** @description Rate limited — slow down and retry after the hinted delay. */
2636
+ 429: {
2637
+ headers: {
2638
+ "RateLimit-Policy": components["headers"]["RateLimit-Policy"];
2639
+ RateLimit: components["headers"]["RateLimit"];
2640
+ "Retry-After": components["headers"]["Retry-After"];
2641
+ [name: string]: unknown;
2642
+ };
2643
+ content: {
2644
+ "application/json": components["schemas"]["Error"];
2645
+ };
2646
+ };
2647
+ /** @description Internal error. */
2648
+ 500: {
2649
+ headers: {
2650
+ [name: string]: unknown;
2651
+ };
2652
+ content: {
2653
+ "application/json": components["schemas"]["Error"];
2654
+ };
2655
+ };
2656
+ /** @description A temporary error occurred. Please try again. */
2657
+ 502: {
2658
+ headers: {
2659
+ [name: string]: unknown;
2660
+ };
2661
+ content: {
2662
+ "application/json": components["schemas"]["Error"];
2663
+ };
2664
+ };
2665
+ /** @description Service unavailable. */
2666
+ 503: {
2667
+ headers: {
2668
+ [name: string]: unknown;
2669
+ };
2670
+ content: {
2671
+ "application/json": components["schemas"]["Error"];
2672
+ };
2673
+ };
2674
+ /** @description Gateway timeout. */
2675
+ 504: {
2676
+ headers: {
2677
+ [name: string]: unknown;
2678
+ };
2679
+ content: {
2680
+ "application/json": components["schemas"]["Error"];
2681
+ };
2682
+ };
2683
+ };
2684
+ };
2685
+ put?: never;
2686
+ post?: never;
2687
+ delete?: never;
2688
+ options?: never;
2689
+ head?: never;
2690
+ patch?: never;
2691
+ trace?: never;
2692
+ };
2489
2693
  "/v1/chats": {
2490
2694
  parameters: {
2491
2695
  query?: never;
@@ -11178,6 +11382,176 @@ interface paths {
11178
11382
  patch?: never;
11179
11383
  trace?: never;
11180
11384
  };
11385
+ "/v1/recruiter/jobs/{job_id}": {
11386
+ parameters: {
11387
+ query?: never;
11388
+ header?: never;
11389
+ path?: never;
11390
+ cookie?: never;
11391
+ };
11392
+ /**
11393
+ * Get job posting
11394
+ * @description Returns one public LinkedIn job posting's full detail (RECRUITER lens) — title, company, location, description, and applicant count. Requires a Recruiter seat.
11395
+ */
11396
+ get: {
11397
+ parameters: {
11398
+ query: {
11399
+ /** @description The connected LinkedIn account to retrieve the job posting on behalf of. */
11400
+ account_id: string;
11401
+ };
11402
+ header?: never;
11403
+ path: {
11404
+ /** @description The numeric id of the job posting, e.g. 4428113858. This is the number in a LinkedIn job URL (https://www.linkedin.com/jobs/view/4428113858) and the job_urn value in a POST /v1/search/jobs result. Pass the number only — a full URL is not accepted by the API (the SDK and CLI extract the id from a URL for you). */
11405
+ job_id: string;
11406
+ };
11407
+ cookie?: never;
11408
+ };
11409
+ requestBody?: never;
11410
+ responses: {
11411
+ /** @description The job posting's full detail (RECRUITER lens — the same job_posting shape as the Core retrieve; content fields are returned verbatim and never stored). Requires a Recruiter seat. */
11412
+ 200: {
11413
+ headers: {
11414
+ "RateLimit-Policy": components["headers"]["RateLimit-Policy"];
11415
+ RateLimit: components["headers"]["RateLimit"];
11416
+ [name: string]: unknown;
11417
+ };
11418
+ content: {
11419
+ "application/json": {
11420
+ /**
11421
+ * @description Response type discriminator.
11422
+ * @enum {string}
11423
+ */
11424
+ object: "job_posting";
11425
+ /** @description The job posting's numeric identifier. */
11426
+ id: string;
11427
+ /** @description Job title (content pass-through — never stored). */
11428
+ title: string;
11429
+ /** @description Hiring company's display name. */
11430
+ company: string;
11431
+ /** @description The hiring company's id — pass it to GET /v1/profiles/companies/{company_id}. */
11432
+ company_id: string;
11433
+ /** @description Posting lifecycle state (e.g. active). */
11434
+ state: string;
11435
+ /** @description Job location, or null when not set. */
11436
+ location: string | null;
11437
+ /** @description Posting cost, in the currency the account bills in. */
11438
+ cost: number;
11439
+ /** @description Number of applicants so far. */
11440
+ applicants_counter: number;
11441
+ /** @description Full job description text (content pass-through — never stored). */
11442
+ description: string;
11443
+ /** @description ISO-8601 UTC timestamp the posting was created, or null when not set. */
11444
+ created_at: string | null;
11445
+ /** @description ISO-8601 UTC timestamp the posting was published, or null when not set. */
11446
+ published_at: string | null;
11447
+ /** @description Hiring team members associated with this posting, when the posting exposes any. */
11448
+ hiring_team: unknown[];
11449
+ };
11450
+ };
11451
+ };
11452
+ /** @description Missing or empty account_id. */
11453
+ 400: {
11454
+ headers: {
11455
+ [name: string]: unknown;
11456
+ };
11457
+ content: {
11458
+ "application/json": components["schemas"]["Error"];
11459
+ };
11460
+ };
11461
+ /** @description Missing or invalid API key, or LinkedIn authentication failed. */
11462
+ 401: {
11463
+ headers: {
11464
+ [name: string]: unknown;
11465
+ };
11466
+ content: {
11467
+ "application/json": components["schemas"]["Error"];
11468
+ };
11469
+ };
11470
+ /** @description The account does not have the required Recruiter seat. */
11471
+ 403: {
11472
+ headers: {
11473
+ [name: string]: unknown;
11474
+ };
11475
+ content: {
11476
+ "application/json": components["schemas"]["Error"];
11477
+ };
11478
+ };
11479
+ /** @description The account_id does not belong to this tenant, or the job posting was not found. */
11480
+ 404: {
11481
+ headers: {
11482
+ [name: string]: unknown;
11483
+ };
11484
+ content: {
11485
+ "application/json": components["schemas"]["Error"];
11486
+ };
11487
+ };
11488
+ /** @description The account is restricted and cannot be queried. */
11489
+ 422: {
11490
+ headers: {
11491
+ [name: string]: unknown;
11492
+ };
11493
+ content: {
11494
+ "application/json": components["schemas"]["Error"];
11495
+ };
11496
+ };
11497
+ /** @description Rate limited — slow down and retry after the hinted delay. */
11498
+ 429: {
11499
+ headers: {
11500
+ "RateLimit-Policy": components["headers"]["RateLimit-Policy"];
11501
+ RateLimit: components["headers"]["RateLimit"];
11502
+ "Retry-After": components["headers"]["Retry-After"];
11503
+ [name: string]: unknown;
11504
+ };
11505
+ content: {
11506
+ "application/json": components["schemas"]["Error"];
11507
+ };
11508
+ };
11509
+ /** @description Internal error. */
11510
+ 500: {
11511
+ headers: {
11512
+ [name: string]: unknown;
11513
+ };
11514
+ content: {
11515
+ "application/json": components["schemas"]["Error"];
11516
+ };
11517
+ };
11518
+ /** @description A temporary error occurred. Please try again. */
11519
+ 502: {
11520
+ headers: {
11521
+ [name: string]: unknown;
11522
+ };
11523
+ content: {
11524
+ "application/json": components["schemas"]["Error"];
11525
+ };
11526
+ };
11527
+ /** @description Service unavailable. */
11528
+ 503: {
11529
+ headers: {
11530
+ [name: string]: unknown;
11531
+ };
11532
+ content: {
11533
+ "application/json": components["schemas"]["Error"];
11534
+ };
11535
+ };
11536
+ /** @description Gateway timeout. */
11537
+ 504: {
11538
+ headers: {
11539
+ [name: string]: unknown;
11540
+ };
11541
+ content: {
11542
+ "application/json": components["schemas"]["Error"];
11543
+ };
11544
+ };
11545
+ };
11546
+ };
11547
+ put?: never;
11548
+ post?: never;
11549
+ delete?: never;
11550
+ options?: never;
11551
+ head?: never;
11552
+ patch?: never;
11553
+ trace?: never;
11554
+ };
11181
11555
  "/v1/recruiter/jobs/{job_id}/applicants": {
11182
11556
  parameters: {
11183
11557
  query?: never;
@@ -15047,6 +15421,11 @@ declare class AccountsResource {
15047
15421
  /**
15048
15422
  * List the tenant's connected LinkedIn accounts, cursor-paginated.
15049
15423
  *
15424
+ * Each item also carries a small set of cached account-detail fields
15425
+ * (`username`, `premium_id`, `public_identifier`, `substrate_created_at`,
15426
+ * `signatures`, `groups`) populated by an async background enrichment —
15427
+ * `null`/`[]` until the account's first enrichment pass completes.
15428
+ *
15050
15429
  * @param params - optional `limit` (1–250) and `cursor` (from a prior page).
15051
15430
  * @returns a page of accounts and the next-page `cursor` (null when exhausted).
15052
15431
  *
@@ -15077,7 +15456,14 @@ declare class AccountsResource {
15077
15456
  createConnectLink(body: AccountConnectLinkBody): Promise<AccountConnectLinkResult>;
15078
15457
  /**
15079
15458
  * Return metadata and current state for one connected account, including the
15080
- * central `quotas[]` view for all tracked quota families.
15459
+ * central `quotas[]` view for all tracked quota families and `seat_id` (the
15460
+ * seat this account occupies, `null` for an admin seatless account).
15461
+ *
15462
+ * This is a stale-while-revalidate read — it always returns immediately
15463
+ * from the cached row (never blocks on a live substrate call), and the
15464
+ * six cached enrichment fields (`username`, `premium_id`,
15465
+ * `public_identifier`, `substrate_created_at`, `signatures`, `groups`) are
15466
+ * `null`/`[]` until the account's first enrichment pass completes.
15081
15467
  */
15082
15468
  get(accountId: string): Promise<AccountDetail>;
15083
15469
  /**
@@ -15200,23 +15586,23 @@ declare class MessagingResource {
15200
15586
  */
15201
15587
 
15202
15588
  /** Strip `account_id` from a query-param type (injected by the account-scoped context). */
15203
- type WithoutAccountId<T> = Omit<T, "account_id">;
15589
+ type WithoutAccountId$1<T> = Omit<T, "account_id">;
15204
15590
  type ProfileDetail = paths["/v1/profiles/me"]["get"]["responses"]["200"]["content"]["application/json"];
15205
15591
  /** Caller-facing query params for `profiles.getMe()` — `account_id` is injected by context. */
15206
- type ProfileGetMeParams = WithoutAccountId<paths["/v1/profiles/me"]["get"]["parameters"]["query"]>;
15592
+ type ProfileGetMeParams = WithoutAccountId$1<paths["/v1/profiles/me"]["get"]["parameters"]["query"]>;
15207
15593
  type ProfileGetResult = paths["/v1/profiles/{profile_id}"]["get"]["responses"]["200"]["content"]["application/json"];
15208
15594
  /** Caller-facing query params for `profiles.get()` — `account_id` is injected by context. */
15209
- type ProfileGetParams = WithoutAccountId<paths["/v1/profiles/{profile_id}"]["get"]["parameters"]["query"]>;
15595
+ type ProfileGetParams = WithoutAccountId$1<paths["/v1/profiles/{profile_id}"]["get"]["parameters"]["query"]>;
15210
15596
  type ConnectionListPage = paths["/v1/profiles/relations"]["get"]["responses"]["200"]["content"]["application/json"];
15211
- type ConnectionListParams = WithoutAccountId<paths["/v1/profiles/relations"]["get"]["parameters"]["query"]>;
15597
+ type ConnectionListParams = WithoutAccountId$1<paths["/v1/profiles/relations"]["get"]["parameters"]["query"]>;
15212
15598
  type FollowerListPage = paths["/v1/profiles/{profile_id}/followers"]["get"]["responses"]["200"]["content"]["application/json"];
15213
- type FollowerListParams = WithoutAccountId<NonNullable<paths["/v1/profiles/{profile_id}/followers"]["get"]["parameters"]["query"]>>;
15599
+ type FollowerListParams = WithoutAccountId$1<NonNullable<paths["/v1/profiles/{profile_id}/followers"]["get"]["parameters"]["query"]>>;
15214
15600
  type ProfilePostListPage = paths["/v1/profiles/{profile_id}/posts"]["get"]["responses"]["200"]["content"]["application/json"];
15215
- type ProfilePostListParams = WithoutAccountId<NonNullable<paths["/v1/profiles/{profile_id}/posts"]["get"]["parameters"]["query"]>>;
15601
+ type ProfilePostListParams = WithoutAccountId$1<NonNullable<paths["/v1/profiles/{profile_id}/posts"]["get"]["parameters"]["query"]>>;
15216
15602
  type ProfileCommentListPage = paths["/v1/profiles/{profile_id}/comments"]["get"]["responses"]["200"]["content"]["application/json"];
15217
- type ProfileCommentListParams = WithoutAccountId<NonNullable<paths["/v1/profiles/{profile_id}/comments"]["get"]["parameters"]["query"]>>;
15603
+ type ProfileCommentListParams = WithoutAccountId$1<NonNullable<paths["/v1/profiles/{profile_id}/comments"]["get"]["parameters"]["query"]>>;
15218
15604
  type ProfileReactionListPage = paths["/v1/profiles/{profile_id}/reactions"]["get"]["responses"]["200"]["content"]["application/json"];
15219
- type ProfileReactionListParams = WithoutAccountId<NonNullable<paths["/v1/profiles/{profile_id}/reactions"]["get"]["parameters"]["query"]>>;
15605
+ type ProfileReactionListParams = WithoutAccountId$1<NonNullable<paths["/v1/profiles/{profile_id}/reactions"]["get"]["parameters"]["query"]>>;
15220
15606
  type CompanyProfile = paths["/v1/profiles/companies/{company_id}"]["get"]["responses"]["200"]["content"]["application/json"];
15221
15607
  type EndorseBody = paths["/v1/profiles/{profile_id}/endorse"]["post"]["requestBody"]["content"]["application/json"];
15222
15608
  type EndorseResult = paths["/v1/profiles/{profile_id}/endorse"]["post"]["responses"]["200"]["content"]["application/json"];
@@ -15492,12 +15878,48 @@ declare class SalesNavigatorResource {
15492
15878
  }
15493
15879
 
15494
15880
  /**
15495
- * Recruiter resource — 17 methods (tier: recruiter).
15881
+ * Jobs resource — 1 method.
15882
+ *
15883
+ * Account-scoped: the bound context injects `account_id` into every request.
15884
+ */
15885
+
15886
+ /** Strip `account_id` from a query-param type (injected by the account-scoped context). */
15887
+ type WithoutAccountId<T> = Omit<T, "account_id">;
15888
+ /**
15889
+ * The job-posting shape returned by `jobs.get()` and `recruiter.getJob()` —
15890
+ * the two endpoints return the same shape (Core vs. Recruiter lens), so this
15891
+ * is the single canonical type; `recruiter.ts` reuses it rather than
15892
+ * deriving a duplicate from its own path.
15893
+ */
15894
+ type JobPosting = paths["/v1/jobs/{job_id}"]["get"]["responses"]["200"]["content"]["application/json"];
15895
+ /** Caller-facing query params for `jobs.get()` — `account_id` is injected by context. */
15896
+ type JobGetParams = WithoutAccountId<paths["/v1/jobs/{job_id}"]["get"]["parameters"]["query"]>;
15897
+ declare class JobsResource {
15898
+ protected readonly ctx: RequestContext;
15899
+ constructor(ctx: RequestContext);
15900
+ /**
15901
+ * Retrieve one public LinkedIn job posting's full detail.
15902
+ * `GET /v1/jobs/{job_id}`
15903
+ *
15904
+ * Accepts a bare numeric job id or a full job URL
15905
+ * (`https://www.linkedin.com/jobs/view/{id}`) — the id is extracted
15906
+ * client-side; the wire request always carries the numeric id. Throws
15907
+ * `CurviateError({ code: 'INVALID_REQUEST' })` synchronously if neither
15908
+ * form can be recognized.
15909
+ * The `account_id` is injected by the account-scoped context.
15910
+ */
15911
+ get(jobIdOrUrl: string, params?: JobGetParams): Promise<JobPosting>;
15912
+ }
15913
+
15914
+ /**
15915
+ * Recruiter resource — 18 methods (tier: recruiter).
15496
15916
  *
15497
15917
  * Account-scoped: the bound context injects `account_id` into every request.
15498
15918
  * `startChat` accepts optional `attachments[]`, `voice_message`, and
15499
15919
  * `video_message`; the SDK builds the `FormData` body automatically.
15500
15920
  * `downloadResume` returns `Promise<ArrayBuffer>` (binary response).
15921
+ * `getJob` returns the same `JobPosting` shape as `jobs.get()` — reused, not
15922
+ * redefined, since both endpoints share the underlying job-posting retrieve.
15501
15923
  */
15502
15924
 
15503
15925
  type RecruiterSyncMessagesParams = NonNullable<paths["/v1/recruiter/messages/sync"]["get"]["parameters"]["query"]>;
@@ -15613,6 +16035,18 @@ declare class RecruiterResource {
15613
16035
  * `POST /v1/recruiter/jobs/{job_id}/checkpoint`
15614
16036
  */
15615
16037
  solveJobCheckpoint(jobId: string, body: RecruiterSolveJobCheckpointBody): Promise<RecruiterSolveJobCheckpointResult>;
16038
+ /**
16039
+ * Get a job posting via the Recruiter lens (any public posting, not only
16040
+ * the operator's own). `GET /v1/recruiter/jobs/{job_id}`
16041
+ *
16042
+ * Accepts a bare numeric job id or a full job URL
16043
+ * (`https://www.linkedin.com/jobs/view/{id}`) — the id is extracted
16044
+ * client-side, mirroring `jobs.get()`. Throws
16045
+ * `CurviateError({ code: 'INVALID_REQUEST' })` synchronously if neither
16046
+ * form can be recognized. Returns the same `JobPosting` shape as
16047
+ * `jobs.get()`.
16048
+ */
16049
+ getJob(jobIdOrUrl: string): Promise<JobPosting>;
15616
16050
  /**
15617
16051
  * List applicants for a job posting.
15618
16052
  * `GET /v1/recruiter/jobs/{job_id}/applicants`
@@ -15691,9 +16125,9 @@ declare class WebhooksResource {
15691
16125
  * Resource namespace assembly.
15692
16126
  *
15693
16127
  * The root client and every `account(id)` accessor expose the same set of
15694
- * resource namespaces. All 9 namespaces are fully implemented:
16128
+ * resource namespaces. All 10 namespaces are fully implemented:
15695
16129
  * accounts, messaging, profiles, invites, search, posts,
15696
- * salesNavigator, recruiter, and webhooks.
16130
+ * salesNavigator, recruiter, jobs, and webhooks.
15697
16131
  */
15698
16132
 
15699
16133
  /** The full namespace surface, shared by the root client and account scopes. */
@@ -15706,6 +16140,7 @@ interface ResourceNamespaces {
15706
16140
  posts: PostsResource;
15707
16141
  salesNavigator: SalesNavigatorResource;
15708
16142
  recruiter: RecruiterResource;
16143
+ jobs: JobsResource;
15709
16144
  webhooks: WebhooksResource;
15710
16145
  }
15711
16146
  /**
@@ -15739,6 +16174,7 @@ declare class Curviate {
15739
16174
  readonly posts: PostsResource;
15740
16175
  readonly salesNavigator: SalesNavigatorResource;
15741
16176
  readonly recruiter: RecruiterResource;
16177
+ readonly jobs: JobsResource;
15742
16178
  readonly webhooks: WebhooksResource;
15743
16179
  constructor(config: CurviateConfig);
15744
16180
  /**
package/dist/index.js CHANGED
@@ -308,6 +308,11 @@ var AccountsResource = class {
308
308
  /**
309
309
  * List the tenant's connected LinkedIn accounts, cursor-paginated.
310
310
  *
311
+ * Each item also carries a small set of cached account-detail fields
312
+ * (`username`, `premium_id`, `public_identifier`, `substrate_created_at`,
313
+ * `signatures`, `groups`) populated by an async background enrichment —
314
+ * `null`/`[]` until the account's first enrichment pass completes.
315
+ *
311
316
  * @param params - optional `limit` (1–250) and `cursor` (from a prior page).
312
317
  * @returns a page of accounts and the next-page `cursor` (null when exhausted).
313
318
  *
@@ -368,7 +373,14 @@ var AccountsResource = class {
368
373
  }
369
374
  /**
370
375
  * Return metadata and current state for one connected account, including the
371
- * central `quotas[]` view for all tracked quota families.
376
+ * central `quotas[]` view for all tracked quota families and `seat_id` (the
377
+ * seat this account occupies, `null` for an admin seatless account).
378
+ *
379
+ * This is a stale-while-revalidate read — it always returns immediately
380
+ * from the cached row (never blocks on a live substrate call), and the
381
+ * six cached enrichment fields (`username`, `premium_id`,
382
+ * `public_identifier`, `substrate_created_at`, `signatures`, `groups`) are
383
+ * `null`/`[]` until the account's first enrichment pass completes.
372
384
  */
373
385
  get(accountId) {
374
386
  return this.ctx.request({
@@ -1031,6 +1043,21 @@ var SalesNavigatorResource = class {
1031
1043
  }
1032
1044
  };
1033
1045
 
1046
+ // src/internal/job-id.ts
1047
+ var JOB_URL_ID_PATTERN = /\/jobs\/view\/(\d+)/;
1048
+ function resolveJobId(idOrUrl) {
1049
+ const trimmed = idOrUrl.trim();
1050
+ if (/^\d+$/.test(trimmed)) return trimmed;
1051
+ const match = trimmed.match(JOB_URL_ID_PATTERN);
1052
+ if (match) return match[1];
1053
+ throw new CurviateError({
1054
+ code: "INVALID_REQUEST",
1055
+ message: `Could not extract a numeric job id from "${idOrUrl}". Pass a bare numeric id (e.g. "4428113858") or a LinkedIn job URL (e.g. "https://www.linkedin.com/jobs/view/4428113858").`,
1056
+ userFixable: true,
1057
+ retryLikelyToSucceed: false
1058
+ });
1059
+ }
1060
+
1034
1061
  // src/resources/recruiter.ts
1035
1062
  function buildFormData4(scalars, attachments, voice_message, video_message) {
1036
1063
  const form = new FormData();
@@ -1246,6 +1273,24 @@ var RecruiterResource = class {
1246
1273
  accountIdIn: "body"
1247
1274
  });
1248
1275
  }
1276
+ /**
1277
+ * Get a job posting via the Recruiter lens (any public posting, not only
1278
+ * the operator's own). `GET /v1/recruiter/jobs/{job_id}`
1279
+ *
1280
+ * Accepts a bare numeric job id or a full job URL
1281
+ * (`https://www.linkedin.com/jobs/view/{id}`) — the id is extracted
1282
+ * client-side, mirroring `jobs.get()`. Throws
1283
+ * `CurviateError({ code: 'INVALID_REQUEST' })` synchronously if neither
1284
+ * form can be recognized. Returns the same `JobPosting` shape as
1285
+ * `jobs.get()`.
1286
+ */
1287
+ getJob(jobIdOrUrl) {
1288
+ const jobId = resolveJobId(jobIdOrUrl);
1289
+ return this.ctx.request({
1290
+ method: "GET",
1291
+ path: `/v1/recruiter/jobs/${jobId}`
1292
+ });
1293
+ }
1249
1294
  /**
1250
1295
  * List applicants for a job posting.
1251
1296
  * `GET /v1/recruiter/jobs/{job_id}/applicants`
@@ -1280,6 +1325,32 @@ var RecruiterResource = class {
1280
1325
  }
1281
1326
  };
1282
1327
 
1328
+ // src/resources/jobs.ts
1329
+ var JobsResource = class {
1330
+ constructor(ctx) {
1331
+ this.ctx = ctx;
1332
+ }
1333
+ /**
1334
+ * Retrieve one public LinkedIn job posting's full detail.
1335
+ * `GET /v1/jobs/{job_id}`
1336
+ *
1337
+ * Accepts a bare numeric job id or a full job URL
1338
+ * (`https://www.linkedin.com/jobs/view/{id}`) — the id is extracted
1339
+ * client-side; the wire request always carries the numeric id. Throws
1340
+ * `CurviateError({ code: 'INVALID_REQUEST' })` synchronously if neither
1341
+ * form can be recognized.
1342
+ * The `account_id` is injected by the account-scoped context.
1343
+ */
1344
+ get(jobIdOrUrl, params) {
1345
+ const jobId = resolveJobId(jobIdOrUrl);
1346
+ return this.ctx.request({
1347
+ method: "GET",
1348
+ path: `/v1/jobs/${jobId}`,
1349
+ ...params ? { query: params } : {}
1350
+ });
1351
+ }
1352
+ };
1353
+
1283
1354
  // src/resources/webhooks.ts
1284
1355
  var WebhooksResource = class {
1285
1356
  constructor(ctx) {
@@ -1365,6 +1436,7 @@ function buildNamespaces(ctx) {
1365
1436
  posts: new PostsResource(ctx),
1366
1437
  salesNavigator: new SalesNavigatorResource(ctx),
1367
1438
  recruiter: new RecruiterResource(ctx),
1439
+ jobs: new JobsResource(ctx),
1368
1440
  webhooks: new WebhooksResource(ctx)
1369
1441
  };
1370
1442
  }
@@ -1388,6 +1460,7 @@ var Curviate = class {
1388
1460
  this.posts = ns.posts;
1389
1461
  this.salesNavigator = ns.salesNavigator;
1390
1462
  this.recruiter = ns.recruiter;
1463
+ this.jobs = ns.jobs;
1391
1464
  this.webhooks = ns.webhooks;
1392
1465
  }
1393
1466
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curviate/sdk",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "private": false,
5
5
  "description": "TypeScript SDK for the Curviate API.",
6
6
  "license": "MIT",
@@ -55,8 +55,23 @@ export interface paths {
55
55
  headline?: string | null;
56
56
  /** @description The seat this account occupies. */
57
57
  seat_id?: string | null;
58
- /** @description ISO-8601 connection timestamp. */
59
- connected_at?: string;
58
+ /** @description ISO-8601 UTC connection timestamp. */
59
+ connected_at?: string | null;
60
+ /** @description Cached account username. Null until enriched. */
61
+ username?: string | null;
62
+ /** @description Cached premium-membership id. Null until enriched, or for non-premium accounts. */
63
+ premium_id?: string | null;
64
+ /** @description Cached public profile identifier. Null until enriched. */
65
+ public_identifier?: string | null;
66
+ /** @description ISO-8601 UTC creation timestamp of the underlying LinkedIn account — distinct from connected_at. Null until enriched. */
67
+ substrate_created_at?: string | null;
68
+ /** @description Cached signature blocks (title + content) for the account. Empty until enriched. */
69
+ signatures?: {
70
+ title?: string;
71
+ content?: string;
72
+ }[];
73
+ /** @description Cached group names the account belongs to. Empty until enriched. */
74
+ groups?: string[];
60
75
  }[];
61
76
  /** @description Next-page cursor; null on the last page. */
62
77
  cursor?: string | null;
@@ -399,9 +414,28 @@ export interface paths {
399
414
  auth_method?: string;
400
415
  full_name?: string | null;
401
416
  headline?: string | null;
417
+ /** @description ISO-8601 UTC connection timestamp. */
402
418
  connected_at?: string | null;
419
+ /** @description ISO-8601 UTC time the account state was last checked. */
403
420
  last_checked_at?: string;
404
- /** @description Per-account quota view one entry per tracked family (messages.daily, connection_requests.daily, profile_views.daily, inmail.daily, account.per_minute). */
421
+ /** @description The seat this account occupies (null for an admin seatless account). */
422
+ seat_id?: string | null;
423
+ /** @description Cached account username. Null until enriched. */
424
+ username?: string | null;
425
+ /** @description Cached premium-membership id. Null until enriched, or for non-premium accounts. */
426
+ premium_id?: string | null;
427
+ /** @description Cached public profile identifier. Null until enriched. */
428
+ public_identifier?: string | null;
429
+ /** @description ISO-8601 UTC creation timestamp of the underlying LinkedIn account — distinct from connected_at. Null until enriched. */
430
+ substrate_created_at?: string | null;
431
+ /** @description Cached signature blocks (title + content) for the account. Empty until enriched. */
432
+ signatures?: {
433
+ title?: string;
434
+ content?: string;
435
+ }[];
436
+ /** @description Cached group names the account belongs to. Empty until enriched. */
437
+ groups?: string[];
438
+ /** @description Usage-safety recommendations for this account — one entry per tracked family (messages.daily, connection_requests.daily, profile_views.daily, inmail.daily, profile.endorse, account.per_minute). These are advisory only: Curviate never rejects a request because a daily recommendation is exceeded; only account.per_minute is a binding limit enforced with HTTP 429. */
405
439
  quotas?: {
406
440
  /** @description Quota family (e.g. messages.daily, account.per_minute). */
407
441
  quota_name?: string;
@@ -412,7 +446,7 @@ export interface paths {
412
446
  /** @description ISO-8601 UTC time the current window resets. */
413
447
  reset_time?: string;
414
448
  /**
415
- * @description Pacing hint.
449
+ * @description Pacing recommendation for this family, advisory only. `none` (under 80% consumed), `slow_down` (80-99% consumed), and `backoff` (100%+ consumed) never block a request. `stop` is reserved exclusively for `account.per_minute` — the sole binding limit, whose breach is enforced with HTTP 429.
416
450
  * @enum {string}
417
451
  */
418
452
  recommended_throttle_hint?: "none" | "slow_down" | "backoff" | "stop";
@@ -2377,6 +2411,176 @@ export interface paths {
2377
2411
  patch?: never;
2378
2412
  trace?: never;
2379
2413
  };
2414
+ "/v1/jobs/{job_id}": {
2415
+ parameters: {
2416
+ query?: never;
2417
+ header?: never;
2418
+ path?: never;
2419
+ cookie?: never;
2420
+ };
2421
+ /**
2422
+ * Get job posting
2423
+ * @description Returns one public LinkedIn job posting's full detail — title, company, location, description, and applicant count.
2424
+ */
2425
+ get: {
2426
+ parameters: {
2427
+ query: {
2428
+ /** @description The connected LinkedIn account to retrieve the job posting on behalf of. */
2429
+ account_id: string;
2430
+ };
2431
+ header?: never;
2432
+ path: {
2433
+ /** @description The numeric id of the job posting, e.g. 4428113858. This is the number in a LinkedIn job URL (https://www.linkedin.com/jobs/view/4428113858) and the job_urn value in a POST /v1/search/jobs result. Pass the number only — a full URL is not accepted by the API (the SDK and CLI extract the id from a URL for you). */
2434
+ job_id: string;
2435
+ };
2436
+ cookie?: never;
2437
+ };
2438
+ requestBody?: never;
2439
+ responses: {
2440
+ /** @description The job posting's full detail. Content fields (title, description) are returned verbatim and are never stored. */
2441
+ 200: {
2442
+ headers: {
2443
+ "RateLimit-Policy": components["headers"]["RateLimit-Policy"];
2444
+ RateLimit: components["headers"]["RateLimit"];
2445
+ [name: string]: unknown;
2446
+ };
2447
+ content: {
2448
+ "application/json": {
2449
+ /**
2450
+ * @description Response type discriminator.
2451
+ * @enum {string}
2452
+ */
2453
+ object: "job_posting";
2454
+ /** @description The job posting's numeric identifier. */
2455
+ id: string;
2456
+ /** @description Job title (content pass-through — never stored). */
2457
+ title: string;
2458
+ /** @description Hiring company's display name. */
2459
+ company: string;
2460
+ /** @description The hiring company's id — pass it to GET /v1/profiles/companies/{company_id}. */
2461
+ company_id: string;
2462
+ /** @description Posting lifecycle state (e.g. active). */
2463
+ state: string;
2464
+ /** @description Job location, or null when not set. */
2465
+ location: string | null;
2466
+ /** @description Posting cost, in the currency the account bills in. */
2467
+ cost: number;
2468
+ /** @description Number of applicants so far. */
2469
+ applicants_counter: number;
2470
+ /** @description Full job description text (content pass-through — never stored). */
2471
+ description: string;
2472
+ /** @description ISO-8601 UTC timestamp the posting was created, or null when not set. */
2473
+ created_at: string | null;
2474
+ /** @description ISO-8601 UTC timestamp the posting was published, or null when not set. */
2475
+ published_at: string | null;
2476
+ /** @description Hiring team members associated with this posting, when the posting exposes any. */
2477
+ hiring_team: unknown[];
2478
+ };
2479
+ };
2480
+ };
2481
+ /** @description Missing or empty account_id. */
2482
+ 400: {
2483
+ headers: {
2484
+ [name: string]: unknown;
2485
+ };
2486
+ content: {
2487
+ "application/json": components["schemas"]["Error"];
2488
+ };
2489
+ };
2490
+ /** @description Missing or invalid API key. */
2491
+ 401: {
2492
+ headers: {
2493
+ [name: string]: unknown;
2494
+ };
2495
+ content: {
2496
+ "application/json": components["schemas"]["Error"];
2497
+ };
2498
+ };
2499
+ /** @description The account does not have the required Core seat. */
2500
+ 403: {
2501
+ headers: {
2502
+ [name: string]: unknown;
2503
+ };
2504
+ content: {
2505
+ "application/json": components["schemas"]["Error"];
2506
+ };
2507
+ };
2508
+ /** @description The account_id does not belong to this tenant, or the job posting was not found. */
2509
+ 404: {
2510
+ headers: {
2511
+ [name: string]: unknown;
2512
+ };
2513
+ content: {
2514
+ "application/json": components["schemas"]["Error"];
2515
+ };
2516
+ };
2517
+ /** @description The account is restricted and cannot be queried. */
2518
+ 422: {
2519
+ headers: {
2520
+ [name: string]: unknown;
2521
+ };
2522
+ content: {
2523
+ "application/json": components["schemas"]["Error"];
2524
+ };
2525
+ };
2526
+ /** @description Rate limited — slow down and retry after the hinted delay. */
2527
+ 429: {
2528
+ headers: {
2529
+ "RateLimit-Policy": components["headers"]["RateLimit-Policy"];
2530
+ RateLimit: components["headers"]["RateLimit"];
2531
+ "Retry-After": components["headers"]["Retry-After"];
2532
+ [name: string]: unknown;
2533
+ };
2534
+ content: {
2535
+ "application/json": components["schemas"]["Error"];
2536
+ };
2537
+ };
2538
+ /** @description Internal error. */
2539
+ 500: {
2540
+ headers: {
2541
+ [name: string]: unknown;
2542
+ };
2543
+ content: {
2544
+ "application/json": components["schemas"]["Error"];
2545
+ };
2546
+ };
2547
+ /** @description A temporary error occurred. Please try again. */
2548
+ 502: {
2549
+ headers: {
2550
+ [name: string]: unknown;
2551
+ };
2552
+ content: {
2553
+ "application/json": components["schemas"]["Error"];
2554
+ };
2555
+ };
2556
+ /** @description Service unavailable. */
2557
+ 503: {
2558
+ headers: {
2559
+ [name: string]: unknown;
2560
+ };
2561
+ content: {
2562
+ "application/json": components["schemas"]["Error"];
2563
+ };
2564
+ };
2565
+ /** @description Gateway timeout. */
2566
+ 504: {
2567
+ headers: {
2568
+ [name: string]: unknown;
2569
+ };
2570
+ content: {
2571
+ "application/json": components["schemas"]["Error"];
2572
+ };
2573
+ };
2574
+ };
2575
+ };
2576
+ put?: never;
2577
+ post?: never;
2578
+ delete?: never;
2579
+ options?: never;
2580
+ head?: never;
2581
+ patch?: never;
2582
+ trace?: never;
2583
+ };
2380
2584
  "/v1/chats": {
2381
2585
  parameters: {
2382
2586
  query?: never;
@@ -11069,6 +11273,176 @@ export interface paths {
11069
11273
  patch?: never;
11070
11274
  trace?: never;
11071
11275
  };
11276
+ "/v1/recruiter/jobs/{job_id}": {
11277
+ parameters: {
11278
+ query?: never;
11279
+ header?: never;
11280
+ path?: never;
11281
+ cookie?: never;
11282
+ };
11283
+ /**
11284
+ * Get job posting
11285
+ * @description Returns one public LinkedIn job posting's full detail (RECRUITER lens) — title, company, location, description, and applicant count. Requires a Recruiter seat.
11286
+ */
11287
+ get: {
11288
+ parameters: {
11289
+ query: {
11290
+ /** @description The connected LinkedIn account to retrieve the job posting on behalf of. */
11291
+ account_id: string;
11292
+ };
11293
+ header?: never;
11294
+ path: {
11295
+ /** @description The numeric id of the job posting, e.g. 4428113858. This is the number in a LinkedIn job URL (https://www.linkedin.com/jobs/view/4428113858) and the job_urn value in a POST /v1/search/jobs result. Pass the number only — a full URL is not accepted by the API (the SDK and CLI extract the id from a URL for you). */
11296
+ job_id: string;
11297
+ };
11298
+ cookie?: never;
11299
+ };
11300
+ requestBody?: never;
11301
+ responses: {
11302
+ /** @description The job posting's full detail (RECRUITER lens — the same job_posting shape as the Core retrieve; content fields are returned verbatim and never stored). Requires a Recruiter seat. */
11303
+ 200: {
11304
+ headers: {
11305
+ "RateLimit-Policy": components["headers"]["RateLimit-Policy"];
11306
+ RateLimit: components["headers"]["RateLimit"];
11307
+ [name: string]: unknown;
11308
+ };
11309
+ content: {
11310
+ "application/json": {
11311
+ /**
11312
+ * @description Response type discriminator.
11313
+ * @enum {string}
11314
+ */
11315
+ object: "job_posting";
11316
+ /** @description The job posting's numeric identifier. */
11317
+ id: string;
11318
+ /** @description Job title (content pass-through — never stored). */
11319
+ title: string;
11320
+ /** @description Hiring company's display name. */
11321
+ company: string;
11322
+ /** @description The hiring company's id — pass it to GET /v1/profiles/companies/{company_id}. */
11323
+ company_id: string;
11324
+ /** @description Posting lifecycle state (e.g. active). */
11325
+ state: string;
11326
+ /** @description Job location, or null when not set. */
11327
+ location: string | null;
11328
+ /** @description Posting cost, in the currency the account bills in. */
11329
+ cost: number;
11330
+ /** @description Number of applicants so far. */
11331
+ applicants_counter: number;
11332
+ /** @description Full job description text (content pass-through — never stored). */
11333
+ description: string;
11334
+ /** @description ISO-8601 UTC timestamp the posting was created, or null when not set. */
11335
+ created_at: string | null;
11336
+ /** @description ISO-8601 UTC timestamp the posting was published, or null when not set. */
11337
+ published_at: string | null;
11338
+ /** @description Hiring team members associated with this posting, when the posting exposes any. */
11339
+ hiring_team: unknown[];
11340
+ };
11341
+ };
11342
+ };
11343
+ /** @description Missing or empty account_id. */
11344
+ 400: {
11345
+ headers: {
11346
+ [name: string]: unknown;
11347
+ };
11348
+ content: {
11349
+ "application/json": components["schemas"]["Error"];
11350
+ };
11351
+ };
11352
+ /** @description Missing or invalid API key, or LinkedIn authentication failed. */
11353
+ 401: {
11354
+ headers: {
11355
+ [name: string]: unknown;
11356
+ };
11357
+ content: {
11358
+ "application/json": components["schemas"]["Error"];
11359
+ };
11360
+ };
11361
+ /** @description The account does not have the required Recruiter seat. */
11362
+ 403: {
11363
+ headers: {
11364
+ [name: string]: unknown;
11365
+ };
11366
+ content: {
11367
+ "application/json": components["schemas"]["Error"];
11368
+ };
11369
+ };
11370
+ /** @description The account_id does not belong to this tenant, or the job posting was not found. */
11371
+ 404: {
11372
+ headers: {
11373
+ [name: string]: unknown;
11374
+ };
11375
+ content: {
11376
+ "application/json": components["schemas"]["Error"];
11377
+ };
11378
+ };
11379
+ /** @description The account is restricted and cannot be queried. */
11380
+ 422: {
11381
+ headers: {
11382
+ [name: string]: unknown;
11383
+ };
11384
+ content: {
11385
+ "application/json": components["schemas"]["Error"];
11386
+ };
11387
+ };
11388
+ /** @description Rate limited — slow down and retry after the hinted delay. */
11389
+ 429: {
11390
+ headers: {
11391
+ "RateLimit-Policy": components["headers"]["RateLimit-Policy"];
11392
+ RateLimit: components["headers"]["RateLimit"];
11393
+ "Retry-After": components["headers"]["Retry-After"];
11394
+ [name: string]: unknown;
11395
+ };
11396
+ content: {
11397
+ "application/json": components["schemas"]["Error"];
11398
+ };
11399
+ };
11400
+ /** @description Internal error. */
11401
+ 500: {
11402
+ headers: {
11403
+ [name: string]: unknown;
11404
+ };
11405
+ content: {
11406
+ "application/json": components["schemas"]["Error"];
11407
+ };
11408
+ };
11409
+ /** @description A temporary error occurred. Please try again. */
11410
+ 502: {
11411
+ headers: {
11412
+ [name: string]: unknown;
11413
+ };
11414
+ content: {
11415
+ "application/json": components["schemas"]["Error"];
11416
+ };
11417
+ };
11418
+ /** @description Service unavailable. */
11419
+ 503: {
11420
+ headers: {
11421
+ [name: string]: unknown;
11422
+ };
11423
+ content: {
11424
+ "application/json": components["schemas"]["Error"];
11425
+ };
11426
+ };
11427
+ /** @description Gateway timeout. */
11428
+ 504: {
11429
+ headers: {
11430
+ [name: string]: unknown;
11431
+ };
11432
+ content: {
11433
+ "application/json": components["schemas"]["Error"];
11434
+ };
11435
+ };
11436
+ };
11437
+ };
11438
+ put?: never;
11439
+ post?: never;
11440
+ delete?: never;
11441
+ options?: never;
11442
+ head?: never;
11443
+ patch?: never;
11444
+ trace?: never;
11445
+ };
11072
11446
  "/v1/recruiter/jobs/{job_id}/applicants": {
11073
11447
  parameters: {
11074
11448
  query?: never;